Подсчёт и хранение количества материалов в ноде определённого типа.

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

Аватар пользователя Strycker Strycker 24 августа 2012 в 11:50

Добрый день.

Помогите с решением задачи.

Дано: в проекте есть основной тип материала - карточка пользователя (не путать с профилем пользователя). Это тип материалов, в котором подробно описывается пользователь сайта. Этот документ единственный для каждого пользователя. Есть другие типы материалов которые может создавать пользователь (их число неограниченно), например TypeA, TypeB, TypeC и т.д.
Задача стоит следующим образом: надо сделать вьюшку, в которой будут выводиться все карточки пользователей а так же подсчитываться количество документов определённых типов, и количество записей в поле C карточки пользователя, т.е. надо сделать вьюшку следующего вида:

User Card | TypeA_Count | TypeB_Count | FieldC_Count

Card1           26             12            4
Card2           13             8             2
Card3           4              3             0

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

Как я решаю эту задачу: Я сделал в карточке пользователя 3 поля, внутри которых хранится искомое количество документов и записей в поле. Заполнять эти поля, планирую в момент создания пользователем новой ноды указанного типа. Т.е. я использую хук menu_alter, в котором задаю callback-функцию, внутри которой считаю количество уже существующих материалов нужного типа, делаю +1 и пытаюсь сохранить в поле ноды "карточка пользователя". Не работает Sad

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

P.S. Вставлю часть кода модуля, чтоб не быть голословным:

<?php    function docs_count_menu_alter(&$items) {
        
$items['node/add/doc']['page callback'] = 'docs_count_article_page_callback';
        
$items['node/add/pic']['page callback'] = 'docs_count_pic_page_callback';
    }
    
    function 
docs_count_article_page_callback() {
        global 
$user;
        global 
$node;
        
        if (
$user->uid == 0)
            return 
node_add('doc');
        
        
$count db_query("SELECT COUNT(*) FROM {node} n 
WHERE n.uid = 
$user->uid AND n.type = 'doc'")->fetchField();
        
        if (
$count 0) {
            
$node->field_docs_count['ru'][0]['value'] = $count;
        }
        
        return 
node_add('doc');
    }
?>

Комментарии

Аватар пользователя kalabro kalabro 24 августа 2012 в 12:17

"Strycker" wrote:
Делать подсчёт количества нод внутри вьюшки

ну, я б сделала вьюсом для начала. Views это конструктор запросов, а вам и нужен запрос. Кеш тоже никто не отменял
"Strycker" wrote:
P.S. Вставлю часть кода модуля, чтоб не быть голословным:

вы суровый
есть хуки на «после создания ноды» (http://api.drupal.org/api/drupal/modules%21node%21node.api.php/function/...). Но вам надо будет не забыть и про неопубликованное/опубликованное, и про удаленные ноды, и про смену автора и короче куча всего.

$node->field_docs_count['ru'][0]['value']

'und' там поставьте, может и заработает, но я б это сожгла Sad

Аватар пользователя Strycker Strycker 24 августа 2012 в 12:27

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

kalabro wrote:
вы суровый

В смысле?

kalabro wrote:
есть хуки на «после создания ноды» (http://api.drupal.org/api/drupal/modules%21node%21node.api.php/function/...).

Точно, этот хук будет логичнее использовать.

kalabro wrote:
Но вам надо будет не забыть и про неопубликованное/опубликованное, и про удаленные ноды, и про смену автора и короче куча всего.

Да, про это я не подумал. Надо вставить проверки.

kalabro wrote:
но я б это сожгла :(

Почему?

Аватар пользователя kalabro kalabro 24 августа 2012 в 12:48

кстати вот ещё материал http://xandeadx.ru/blog/drupal/505 но я думаю что для Views 3 он может и не понадобиться

"Strycker" wrote:
В смысле?

"Strycker" wrote:
Почему?

потому что код ацкий Smile гляньте ещё в сторону каких нибудь computed fields (я не пользовалась). они должны заботиться о своевременном пересчете полей по крайней мере.

Аватар пользователя Strycker Strycker 24 августа 2012 в 16:16

kalabro wrote:
гляньте ещё в сторону каких нибудь computed fields (я не пользовалась). они должны заботиться о своевременном пересчете полей по крайней мере.

К сожалению, в документации к этому модулю написано: «The field will not work in views »

Аватар пользователя Strycker Strycker 24 августа 2012 в 17:10

Переписал код модуля, сделал через хук node_insert()

<?php    function docs_count_node_insert($node) {
        global 
$user;
        
        if (
$node->type == 'doc') {    
            
$count db_query("SELECT COUNT(*) FROM {node} n 
WHERE n.uid = 
$user->uid AND n.status = 1 
AND n.type = 'doc'"
)->fetchField();
            
$node->field_doc_count['und'][0]['value'] = $count;
        }
    }
?>

Всё равно не работает. Не могу понять почему.

Аватар пользователя Strycker Strycker 24 августа 2012 в 18:33

А! Я понял почему не работает: $node содержит другой объект - сохраняемую ноду, а не ноду карточки, куда надо сохранить посчитанное значение. Сразу же встаёт другой вопрос: как теперь корректно изменить поле совсем другой ноды, а не той, что в данный момент сохраняется?

Аватар пользователя kalabro kalabro 24 августа 2012 в 18:39

что вы делаете? вам надо найти ноду, соответствующую карточке юзера, положить в нее ваш $count и сделать node_save().
p.s. не $user->uid а $node->uid

Аватар пользователя Strycker Strycker 24 августа 2012 в 18:57

"RxB" wrote:
Но вы занимаетесь хернёй

Аргументируйте

"RxB" wrote:
Загрузить.
Изменить.
Сохранить.

Сделал так, после чего сервер упал:

<?php
    
function docs_count_node_insert($node) {
        
        if (
$node->type == 'doc') {    
            
$count db_query("SELECT COUNT(*) FROM {node} n WHERE n.uid = $node->uid 
AND n.type = 'doc'"
)->fetchField();
            if (
$count >= 1) {
                
$nid db_query("SELECT n.nid FROM {node} n where n.uid = $node->uid 
AND n.type = 'user_card'"
)->fetchField();
                
$user_card node_load($nid);
                
$user_card->field_docs_count['ru'][0]['value'] = $count;
                
node_save($user_card);
            }
        }
    }    
?>

Поэтому и спрашиваю, как сделать правильно. Пока опыта программирования под Друпал мало.

Аватар пользователя Strycker Strycker 24 августа 2012 в 18:58

Разве в Notepad++ есть php-валидатор? Wink

Да пропустил одну точку с запятой, исправил. И в целом код подправил, всё равно не записывает в поле. Куда копать?

Аватар пользователя Strycker Strycker 24 августа 2012 в 19:22

"kalabro" wrote:
ну сказала же,LANGUAGE_NONE. ппц какойто, молодой человек.

"Спокойней, спокойней" (с) Wink

Работает с 'und'. Спасибо за комментарий