upd: Все зашло слишком далеко. Можно читать с этого комментария.
Вообще задача заключается в том чтобы после создания материала типа B, прикрепить его к ранее созданному материалу типа A.
Я написал правило rules, которое реагирует на событие создания нового материала типа A и в action "Execute custom PHP code" программно создает материал типа B.
Пишу правило (в том же самом rules добавляю второй action "Execute custom PHP code"), которое после создания материала типа B, прикрепит его к материалу типа A, указав в поле Entity Reference - Autocomplete его заголовок.
<?php
$nid = $node->nid;
$node = node_load($nid);
$node->field_test['und'][0]['value'] = '[node:title]'; // Для тестового <em>Text - Text field</em>
$node->field_location['und'][0]['target_id'] = '[node:title]'; // Для <em>Entity Reference - Autocomplete</em>
node_save($node);
?>
Данный код прекрасно работает с обычным текстовым полем, подставляя значение и сохраняя материал, но с полем Entity Reference - Autocomplete получаю ошибку:
PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'Title' for column 'field_location_target_id' at row 1: INSERT INTO {field_data_field_location} (entity_type, entity_id, revision_id, bundle, delta, language, field_location_target_id) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6); Array ( [:db_insert_placeholder_0] => node [:db_insert_placeholder_1] => 136 [:db_insert_placeholder_2] => 136 [:db_insert_placeholder_3] => server [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => und [:db_insert_placeholder_6] => Title ) in field_sql_storage_field_storage_write() (line 514 of C:\OpenServer\domains\domain.local\modules\field\modules\field_sql_storage\field_sql_storage.module).
ps: field_test['und'][0]['value'] и field_location['und'][0]['target_id'] беру из разметки страницы, как значение аргумента name для input
upd: Поле Entity Reference - Autocomplete в коде представлено двумя полями. Возможно в этом дело?
Комментарии
->target_id = nid
Большое спасибо. Получилось!
<?php
$nid = $node->nid;
$nid2 = $nid + 1;
$node = node_load($nid);
$node->field_location['und'][0]['target_id'] = $nid2;
node_save($node);
?>
Правильно ли я понимаю, что данный способ является совершенно ненадежным из-за способа получения $nid2?
А зачем повторно вызавать node_load, если нода уже загружена изначально? Это большой удар по производительности, т.к. есть референсы и эта функция подтянет ноду вместе с референсами и референсами референсов
Спасибо, уберу.
А что касается правила rules для добавления одного материала к другому не подскажете? Потому что мой способ неправильный скорее всего.
Возможно для моей задачи избыточно создание двух типов материала и манипуляции с ними.
Объясню на примере что требуется
1. Создать материал и заполнить поле заголовок "Котопёс"
2. После сохранения получить материал содержащий опрос
То есть посетитель создает материал, где заполняет одно единственное поле, а вопросы голосования создаются автоматически.
Небольшой прогресс, программно заполняю временными значениями два дефолтных обязательных поля.
<?php
function mymodule_form_node_form_alter(&$form, &$form_state, $form_id) {
if ($form['type']['#value'] == 'poll') {
$form['choice_wrapper']['choice']['new:0']['chtext']['#default_value'] = '1';
$form['choice_wrapper']['choice']['new:1']['chtext']['#default_value'] = '2';
}
}
?>
Ищу способ добавить больше полей с вариантами ответов.
В Rules создал правило, которое после сохранения материала, должно добавить нужные мне варианты ответов в опрос (модуль poll)
<?php
$options = array(
0 => 'vote 1',
1 => 'vote 2',
2 => 'vote 3',
3 => 'vote 4',
); $node = node_load($node->nid);
foreach (
$options as $key=>$value) {$node->choice[$key] = array(
'chid' => dechex(time() * rand(5, 50)),
'chtext' => $value,
'chvotes' => 0,
'weight' => $key,
);
} node_save($node);
?>
Финишная прямая, последнее препятствие.
Работа производится с материалом модуля poll.
Проблема заключается в том что данное правило не заменяет существующие (временные, созданные модулем) значения, а дописывает новые.
Пробовал очистить при помощи unset($node->choice); вроде чистит массив но после сохранения все ровно остаются временные поля.
Хелп!
Ансет свойств объекта ноды действительно чистит только объект. Чтобы удалить поля в базе, полям объекта надо присвоить пустые значения, а не сбрасывать их. А скрывать поля лучше не в цсс, а в настройках отображения. Но учитывая постановку задачи, имеет смысл задуматься об альтере формы создания ноды, чтобы опрос сразу из полей формы делался
Создавать и скрывать, чтобы потом переопределить, - не лучший вариант. Создавать надо в нужном месте с нужными значениями. По коду для poll надо смотреть в модуль, но создание нового материала, задача несложная по коду, например:
'title' => $title,
'body' => array(LANGUAGE_NONE => array(array('value' => 'test body'))),
'uid' => $user->uid,
'type' => 'article',
);
$node = node_submit((object) $node);