First one is the content type which I renamed to “Schools”. It has basic input fields. The second one is “Education program”. We want to make a field type called “entity reference” but it doesn’t exist yet.
We need Entity Reference module in order to achieve this, it can be downloaded from here: https://www.drupal.org/project/entityreference
- Download
- Extract to /sites/all/contrib/
- Enable in Drupal administration
Create a field called “school reference”. Name the field type “entity reference” and use any widget you want. It is not important because we won’t display this field in our form. We’ll add reference pro-grammatically.
Configure field and set Target type to “Node”, Entity selection mode to “Simple (with optional filter by bundle)” and Target bundle to “school”.
Now we have two separate content types and it’s time to do some Drupal magic. We will create a custom module, and call it “my_node_actions”.
Create folder with the same name in /sites/all/modules/custom/ directory and inside of my_node_actions/ create a file called “my_node_actions.module”.
This will be a file with both hooks.
Create new hook called “my_node_actions_form_alter”. This hook performs alterations before a form is rendered which allows us to add fields.
Check machine names of fields in education program content type we made in /admin/structure/types/manage/education-program/fields.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function my_node_actions_form_alter(&$form, &$form_state, $form_id){ switch ($form_id) { case 'school_node_form': // id of content type form is machinename_node_form $form['field_education_program_name'] = array ( '#type' => 'textfield', '#title' => t ('Education program'), ); $form['field_education_program_info'] = array ( '#type' => 'textfield', '#title' => t ('Education program information'), ); break; } } |
When user loads “school_node_form”, it will have 2 new fields we just added.
Next step is to save those two fields as separate node of type “Education program” and entity reference to school created with “school_node_form”.
It is achieved with “hook_node_insert”. This hook is invoked from “node_save()” AFTER the database query that will insert the node into the node table is scheduled for execution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | function my_node_actions_node_insert($node){ switch ($node->type) { case 'school': //make sure node of type "school" is saved // Create a node object, and add node properties. $newNode = (object) NULL; $newNode->type = 'education_program'; //content type we created earlier $newNode->uid = $node->uid; $newNode->created = strtotime("now"); $newNode->changed = strtotime("now"); $newNode->status = 1; $newNode->comment = 0; $newNode->promote = 0; $newNode->moderate = 0; $newNode->language = $node->language; $newNode->title= $node->field_education_program_name; //set fields values defined in content type $newNode->field_education_program_name[LANGUAGE_NONE][0]=array( 'value' => $node->field_education_program_name ); $newNode->field_education_program_info[LANGUAGE_NONE][0]=array( 'value' => $node->field_education_program_info ); if (($node->nid) && (!empty($node->nid))){ $newNode->field_school_reference[LANGUAGE_NONE][0] = array( 'target_id' => $node->nid // we target the node id of school returned from hook_node_insert ); }else{ //something really bad happened } node_save($newNode); //save node education_program break; } } |
If you have followed this tutorial well, we have now successfully created two content types – School and Education program with an entity reference to that school.