Куда лучше помещать php код?

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

Аватар пользователя Kottov Kottov 15 июля 2014 в 23:51

Поначалу когда надо было внести дополнительные функции к полям - пользовался тем что вносил php код в поле с php-фильтром.
Оно поначалу очень удобно, наглядно и тп.
Но когда появились станичные куски кода в нескольких полях ноды и каждой получилось много общих фрагментов кода.
Да, еще под конец север стал выдавать такие ошибки.

Error messagePDOException: SQLSTATE[42000] [1203] User хххххххх already has more than 'max_user_connections' active connections in lock_may_be_available() (line 167 of /hsphere/local/home/ххххххх/ххххххххх.org/includes/lock.inc).

Раздробленный код в ноде может быть причиной такого?
Думаю что не должен. Нода по идее должна собираться за одно подключение к базе, даже если код разбросан по полям. (поправьте если не прав)
Ну в любом случае когда уже понял чего хотел добиться и что можно - решил что надо код оптимизировать и собрать в одно место.
Если я код вынесу в модуль а потом также из поля буду вызывать его функцией для вывода результата, то наверное только о этого не будет? (поправьте если не так)
Надо тогда и чтоб модуль сам заполнял поля при подготовке ноды к показу.
Как тогда лучше оставить поля какие использовал, но их почистить. А модулями для каждого типа ноды программно заполнять поля?
Или же вообще их удалить и все даже создавать их программно?

Понял что есть вариант добавлять php код в шаблон, но тогда там будет куча лишнего кода для разных типов нод. Либо их будет куча отдельных. - Это вариант почему-то не нравиться.

Какими хуками это делается (вариант с модулями)?
hook_user_view_alter
hook_node_view_alter
надо будет включать весь свой код в них {}?

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

Комментарии

Аватар пользователя Chyvakoff Chyvakoff 16 июля 2014 в 11:58

В preprocess_node можно поместить, ну или hook_node_load, чтоб на просмотре уже только отображать.

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

А вообще-БД не тянет, код может быть и непричём.
Ну и кэшировать ноды надо, раз их так сложно собрать.
Или вы вообще что-то неправильно делаете.
Может хостера сменить и всё. Какой у вас, кстати?

Аватар пользователя Kottov Kottov 16 июля 2014 в 13:37

Есть код который генерирует ссылки в из данных автора. Такое я думаю надо во время создания/редактирования ноды собрать и сохранить в полях уже как ссылки.
Для это нужен hook_node_presave($node)?
Но даже они должны показываться или нет в зависимости это автор просматривает или нет.
то есть мне постоянно приходится проверять
if ($user->uid <> $node->uid)

и для этог надо подгружать ноду и профили автора и "просматривающего".
$node = node_load($nodeid_current, null, true);
$user = user_load($uid_current, null, true);
$user = user_load($uid_author, null, true);

В других местах, еще больше собираются данных, с терминов таксономии, со связанных нод по entity reference - то есть и их надо подгружать. То есть надо постоянно "дрилить" по "связкам" чтобы получить данные.
Например, просматривая (преед просмотром) из ноды заказы получить поля из профиля автора объявления, связанного с нодой заказа.

То есть это все работа с базой?

Ну и при этом с помощью этих данных обращаться к другим серверам по вебсокету.

Я вот не знаю может перейти на получение данных полей через -

field_get_items() или entity_metadata_wrapper()

но похоже что для них нужно также загрузить ноду

$field_values = field_get_items('node', $node, 'field_name');
$wrapper = entity_metadata_wrapper('node', $node);

то есть получается что разницы особой нет с $node->field_name['en'][und]['value']

С "has more than 'max_user_connections'" - похоже понял в чем было дело. Отслеживал что-то по dpm() и полез обновлять поля в VBO - это наверное вызывало дополнительные вызовы к базе.

У хостера 30 'max_user_connections' - пока для тестирования хватит.

Аватар пользователя Chyvakoff Chyvakoff 16 июля 2014 в 14:02

Это 3 тяжелых запроса.

$node = node_load($nodeid_current, null, true);
$user = user_load($uid_current, null, true);
$user = user_load($uid_author, null, true);

В хуке объект ноды уже есть, его не надо грузить.
Вместо подгрузки текущего юзера напиши просто

global $user;

Для автора из текущего объекта ноды извлеки uid:

$node->uid;

Всё, трёх тяжелых запросов не надо.

А вообще-лучше всё записывай в поля и потом те что можно-отображай.
Есть даже модуль field_permission, может тебе удастся на нём всё сделать

Аватар пользователя Kottov Kottov 16 июля 2014 в 16:28

То есть как "все в поля"?
php код в поля - так тогда те 3 тяжелых нужно будет грузить и в каждом поле отдельно

или я не понял?

пока намереваюсь переносить код в модули (и если там объект ноды уже есть - то еще лучше) и буду программно заполнять результатами созданные ранее поля

field_permission - по немногу использую - но он делает только ограничения в сторону от автора
а мне как раз наоборот, всем нужно посказать генерируемые ссылки, итерактивные объекты а автору они никчему

Аватар пользователя Chyvakoff Chyvakoff 17 июля 2014 в 9:01

"Kottov" wrote:
php код в поля

Не очень понял о чём вы.

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

Аватар пользователя Виктор Степаньков ака RxB Виктор Степаньк... 17 июля 2014 в 9:51

"Chyvakoff" wrote:
Это 3 тяжелых запроса.

Это ниодного запроса.
Точнее в худшем случае только
$user = user_load($uid_author, null, true);
Но вот зачем

$user = user_load($uid_current, null, true);
$user = user_load($uid_author, null, true);
мне не понятно.

Аватар пользователя Kottov Kottov 17 июля 2014 в 16:38

Мене в полях хранить нечего. Они у меня должны выдавать значения динамически. То есть я пока там (с включенным php фильтром) "храню" php код который все это делает и в них же выводит.

Вот думал что правильнее его вынести в одно место и от туда программно заполнять поля.
Вот еще такие доводы http://rxb.name/blog/pochemu-ya-protiv-koda-v-blokah-i-nodah-i-modulya-p...

так заполнять чем?
hook_user_view_alter
hook_node_view_alter

К вопросу об экономии на обещании к базе

$node = node_load($nodeid_current, null, true); - нода в хуке уже подгружена, ок, значит это уже не используем
$user = user_load($uid_current, null, true); - без этого есть доступ только к основным полям профиля, а у меня все что нужно в дополнительных, - так что надо будет подгружать
$user = user_load($uid_author, null, true); - ну тут понятно что придется подгружать

Тут еще неожиданно для себя обнаружил что в модуле только в хуках (да и то в определенных только) работает node_load и user_load.
В своей функции я их использовать не могу.
Ну и с передачей значений из одной функции в другую - еще та проблема.
Ну и agr() выдает не внутренний путь, а чистый.

То есть не получится просто взять и перенести код с полей в модуль.
В полях можно не о чем особо не париться, а в модуле надо код разносить по разным хукам, между которыми трудно передавать значения переменных.

Аватар пользователя Chyvakoff Chyvakoff 18 июля 2014 в 10:10

"Kottov" wrote:
Мене в полях хранить нечего.

Тогда зачем вы их создавали? Ради хранения кода?
"Kottov" wrote:
В своей функции я их использовать не могу.

Это почему это?
"Kottov" wrote:
То есть не получится просто взять и перенести код с полей в модуль.

Всё получится.
"Kottov" wrote:
В полях можно не о чем особо не париться, а в модуле надо код разносить по разным хукам, между которыми трудно передавать значения переменных.

В хуках всё гораздо проще, структурированней и вообще это правильно.
А в темизации уже спокойно раскидаете всё как нужно.

Аватар пользователя Kottov Kottov 18 июля 2014 в 15:38

Ну есть поля которые заполняет автор, это понятно.
Другие - нужно же где-то выводить динамическую информацию, привязывать ее к чему-то.
Через что еще делать? Собирать страницу их представлений?
Ну и да код там-же хранил. Для разработки (особенно когда никогда ранее друпал/пхп/сайты не занималься)) удобно.
Вот по тихоньку разобрался (спасибо всем кто помог) и уже можно делать как надо.
Если бы сразу в модули направили - то вряд ли бы осилил.

Если я создаю модуль (без хуков) со своей функцией, то там $node_load user_load не работают
PHP Fatal error: Call to undefined function node_load()

то есть надо их помещать в хуки? и только там они и будут работать. Не будет потом трудностей вызвать эту функцию в другом месте?
Понимаю что как-то уже нашли способ чтоб все эти ограничения увязывались и все что нужно делалось. Но где о таком почитать? Если вообще в целом, структурно (на 2 страницах) чтоб объяснилось что оно задумано чтоб делать так-то и так-то. А то на отдельных примерах, только сам себе собираешь фрагментарно картинку и часто додумываешь.

До темизации вообще пока не дошел.))

Вот нужно чтоб два поля отображались в ряд а не над друг другом - это только нужно в щаблон лезть. И шаблоны под каждый тип материаяла делать. Почему нельзя было в Manage Display - сделать драг-адн-дроп.
Для форм такое видел, но для нод есть такое?

«В хуках всё гораздо проще, структурированней и вообще это правильно.»

Вот вот в целом структуру хуков уловить пока не удается.

Аватар пользователя Chyvakoff Chyvakoff 19 июля 2014 в 22:52

"Kottov" wrote:
Если я создаю модуль (без хуков) со своей функцией, то там $node_load user_load не работают
PHP Fatal error: Call to undefined function node_load()

Странно. А вызываете эту функцию потом где?

Аватар пользователя Kottov Kottov 20 июля 2014 в 5:40

Похоже что понял.
Спасибо.

Если пользовательскую функцию вызывать из хуков то "все" что нужно подгружается автоматически.
Хух, ну тогда жить можно. ))

Аватар пользователя dashiwa dashiwa 20 июля 2014 в 16:18

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

Аватар пользователя Kottov Kottov 22 июля 2014 в 22:52

Должен сказать что $node не подгрузилась автоматически в hook_node_view_alter()

<?php
function my_module_node_view_alter(&$build) {
global 
$user;
//$nodeid_current = arg(1);
//$node = node_load($nodeid_current, null, true);
if ($user->uid <> $node->uid) {print_r("user_uid <> node->uid"); }
}
?>

Выдало

Notice: Undefined variable: node в функции my_module_node_view_alter() (строка 256 в файле /hsphere/local/home/xxxxxxxxxxxxxxxx/sites/all/modules/my_module/my_module.module).
Notice: Trying to get property of non-object в функции _node_view_alter() (строка 256 в файле /hsphere/local/home/xxxxxxxxxxxxxxxx/sites/all/modules/my_module/my_module.module).

без комментов // - заработало

Как понять будет ли в хуке $node или нет?
$node должен быть аргументе функции хука? - тогда он и будет виден?

Аватар пользователя drupby drupby 22 июля 2014 в 23:32

"Kottov" wrote:
$node должен быть аргументе функции хука

устанавливаете модуль devel и потом

function my_module_node_view_alter(&$build) {
 
  dpm($build);// там найдете объект ноды
 
  global $user;
  //$nodeid_current = arg(1);
  //$node = node_load($nodeid_current, null, true);
  if ($user->uid <> $node->uid) {
    print 'user_uid <> node->uid';
  }
}
Аватар пользователя Kottov Kottov 23 июля 2014 в 2:00

Спасибо.
Там конечно есть структура полей, но значений нет. Нет и node id.
То есть то что мене надо, надо делать другим хуком. Но имеено там я ставлю условие подключать яваскрипт или нет. Приходиться все равно стучатся в базу.

Аватар пользователя drupby drupby 23 июля 2014 в 2:26

"Kottov" wrote:
Спасибо.
Там конечно есть структура полей, но значений нет. Нет и node id.

а $build['#node'] куда пропало?
$node = $build['#node'];// и откуда у вас хуки растут?

Аватар пользователя Kottov Kottov 23 июля 2014 в 6:05

не, полностью код был такой

<?phpfunction my_module_node_view_alter(&$build) {
global $user;
//$nodeid_current = arg(1);
//$node = node_load($nodeid_current, null, true);
if ($user->uid <> $node->uid) {print_r("user_uid <> node->uid"); }

$build['#post_render'][] = 'my_module_node_post_render';
}?>

в dpm - #node показывает:

#node (Object) stdClass
∞ (Recursion)
$...['#node']->∞

В документации https://api.drupal.org/api/drupal/modules!node!node.api.php/function/hoo... всего пару строчек.

Alter the results of node_view().

This hook is called after the content has been assembled in a structured array and may be used for doing processing which requires that the complete node content structure has been built.

Каким образом можно было понять что нужно сначала собрать ноду чтоб получать с нее все остальное?

Аватар пользователя Kottov Kottov 23 июля 2014 в 6:32

По взамоодействию между хуков.

Я сделал програмно кнопку с помошью hook_node_view() и hook_field_extra_fields()
С помошью hook_node_view_alter() и drupal_add_js() загрузил явасткрипт чтоб он реагировал на нажатие кнопки и Вызывал ajax запрос my_module_menu_ajax_callback()на выполнение кучи кода, вызывающего и обрабатывающего поля из профилей и нод.

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

Куда мене лучще поместить это условие?
Влоб - это в сам hook_node_view() (так и сделал) - но пришлось продрилить ноду, профили, поля профиля и тд.
В my_module_menu_ajax_callback() - это все уже продрилино - но передать переменыю в hook_node_view() я так понял нельзя.

Можно ли использовать хук в хуке? Или как этот вопрос по нормальному решается?

А то получается что когда в код разбросан по полям с php-фильтром - приходиться все дублировать, так и в хуках получается тоже?

И еще такой вопрос для понимания. Почему хук срабатывает когда его "не просят". Ведь в модуле он просто объявлен как функция к которой надо обратиться чтоб она сработала.
Можно ли обращатся к хукам из других хуков/модулей?

Аватар пользователя Kottov Kottov 23 июля 2014 в 12:05

Фокус в том что наш народ славившийся взамовыручкой, бескорыстием и дружилюбием значительно (и я в том числе) отстал в этом перед прогнившим западом.
Зайдите на http://drupal.stackexchange.com/, https://www.drupal.org, https://github.com/ и увидите по характеру ответов и количеству кода.

edit: Но как минимум одно преимуществ осталось, - прямота.

Аватар пользователя dashiwa dashiwa 23 июля 2014 в 18:15

Kottov wrote:
Фокус в том что наш народ славившийся взамовыручкой, бескорыстием и дружилюбием значительно (и я в том числе) отстал в этом перед прогнившим западом.
Зайдите на http://drupal.stackexchange.com/, https://www.drupal.org, https://github.com/ и увидите по характеру ответов и количеству кода.

edit: Но как минимум одно преимуществ осталось, - прямота.


Не мы такие - жизнь такая Smile

Аватар пользователя drupby drupby 23 июля 2014 в 16:48

"Kottov" wrote:
Зайдите на http://drupal.stackexchange.com/, https://www.drupal.org, https://github.com/ и увидите по характеру ответов и количеству кода.

Вы еще здесь?
Я вам сказал как узнать, где находиться объект ноды, а затем написал строку, которая получает объект - так что же вам еще нужно?

Какие вы ответы ждете? если взять ваш комментарий

"Kottov" wrote:
Опубликовано Kottov в Ср, 23/07/2014 - 05:32

"Kottov" wrote:
На кнопку нужно навесть лейбу

"Kottov" wrote:
пришлось продрилить ноду

"Kottov" wrote:
это все уже продрилино

"Kottov" wrote:
передать переменыю

"Kottov" wrote:
Почему хук срабатывает когда его "не просят"

то я сломал себе весь мозг, пытаясь понять тот поток непонятного мне сознания, который там присутствует - переведите тот коммент на английский и разместите на drupal.stackexchange, хоть будет потом над чем поржать.

Аватар пользователя vlucas vlucas 30 июля 2014 в 12:36

drupby wrote:
"Kottov" wrote:
Зайдите на http://drupal.stackexchange.com/, https://www.drupal.org, https://github.com/ и увидите по характеру ответов и количеству кода.

Вы еще здесь?
Я вам сказал как узнать, где находиться объект ноды, а затем написал строку, которая получает объект - так что же вам еще нужно?

Какие вы ответы ждете? если взять ваш комментарий

"Kottov" wrote:
Опубликовано Kottov в Ср, 23/07/2014 - 05:32

"Kottov" wrote:
На кнопку нужно навесть лейбу

"Kottov" wrote:
пришлось продрилить ноду

"Kottov" wrote:
это все уже продрилино

"Kottov" wrote:
передать переменыю

"Kottov" wrote:
Почему хук срабатывает когда его "не просят"

то я сломал себе весь мозг, пытаясь понять тот поток непонятного мне сознания, который там присутствует - переведите тот коммент на английский и разместите на drupal.stackexchange, хоть будет потом над чем поржать.

)))))

Аватар пользователя Kottov Kottov 23 июля 2014 в 17:22

Drill down - как раз оттуда
"https://www.drupal.org/node/1315566
Apr 4, 2014 - I needed to drill down through a node to a field collection with a term .... Events: After node is updated."
На английском мне было бы гораздо проще писать.
// поверьте мне друпал выносит мозг не меньше, из-за отсутствия нормальной документации и примеров. Если написал что лишнее извините, просто забыл закоментить.

Аватар пользователя drupby drupby 23 июля 2014 в 17:55

"Kottov" wrote:
поверьте мне друпал выносит мозг не меньше, из-за отсутствия нормальной документации и примеров

чем вас не устраивает документация? примеров для друпала тысячи по каждому случаю.проблемы ищите в себе, ну неужели друпал виноват в том, что вы 2 дня не можете найти объект внутри переменной

Аватар пользователя Kottov Kottov 30 июля 2014 в 23:07

Если кто-то из присутствующих никогда не говил "хук", а пользовался как положено - "великим и могучим" - пусть бросит в меня грязью.))

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

А если копнете поглубже то вообще исконно словянских слов даже не половина. Даже "тарелка" у нас немецкая.

Подобная история и с Английским - весь культурный и деловой язык был добавлен норманами.

Так к германскому слову "swine" (свинья), добавилось французкое "pork" - тоже свинья - но стало использоваться в смысле "свинины". Так что замещения не происходит, а наоборот обогощение.

Аватар пользователя Kottov Kottov 30 июля 2014 в 23:09

Для тех кто случайно не дочитал вопросы:

"Надо тогда и чтоб модуль сам заполнял поля при подготовке ноды к показу.
Как тогда лучше оставить поля какие использовал, но их почистить от php кода. А модулями для каждого типа ноды программно заполнять поля?
Или же вообще их удалить и все даже создавать их программно?

Какими хуками это делается (вариант с модулями)?
hook_user_view_alter
hook_node_view_alter"

Аватар пользователя dashiwa dashiwa 31 июля 2014 в 1:37

function hook_node_view($node, $view_mode, $langcode) {
$node->content['my_additional_field'] = array(
'#markup' => $additional_field,
'#weight' => 10,
'#theme' => 'mymodule_my_additional_field',
);
}