The Problem: Content creators entering the same content more than once.
In my case, the content items entered are jewellery items. The Title of the Jewellery Item content type is the SKU. Often times the same jewellery item is being entered more than once. Drupal allows for duplicate titles. Thus, the content creators are unaware of the duplicate entries.
Clearly this is not ideal. Duplicate content creates confusion across the board. Not to mention administration issues. From a Search Engine perspective, duplicate content is a no-no.
The solution: On the creation of a new Jewellery Item. Check if the Jewellery Item Title being entered is in the database or not.
The Process
When the node creation form is submitted. We want to validate that the Title being entered is not already in the database. If it is, return the user to the node creation form with a message. The message states that the Title already exists.
We will make use of HOOK_form_alter()
within a custom module. Within this function, we will declare a custom form validation function.
I usually have a custom module within my site that takes care of functionality such as this. Summary of steps:
- Get the form id of the Jewellery Item node creation form.
- Within our custom module, declare the
HOOK_form_alter()
function. - Within the
HOOK_form_alter()
function, declare a custom form validate function - Test and deploy.
Get the Form ID
Within our HOOK_form_alter()
function, we will need to check for the form id. This will ensure we are working with the correct form. To get the form id:
- Open the node creation form for the content type we are working with. In my case, Jewellery Item.
- Inspect the code. In Google Chrome, Ctrl+Shift+I will open the inspector pane.
- Look for the opening
<form
tag. Here you will seeid="node-node-type-form"
. We will use this value in our function.
The HOOK_form_alter() Function
In our custom module we add our HOOK_form_alter()
function. This function is executed when a form is submitted. Since it is executed when any form is submitted, we need to check for the form id of the node creation form.
Earlier we got the form id from inspecting the code. id="node-jewellery-item-form"
. To get the form id we need to change the - to _. so the form id is node_jewellery_item_form
With in the if statement we declare a custom form validation function. The code looks something like this:
/** * Implements Hook_form_alter for node 'My Node Type' */ function my_module_form_alter (&$form, &$form_state, $form_id) { // Create Jewellery Item node if ($form_id === 'node_jewellery_item_form') { $form['#validate'][] = 'check_title_exists'; } }
Our validation fuction will be named check_title_exists
.
The Custom Validation Function
The validation function will do the following:
- Get the value of the Title Entered
- Query the database for all Jewellery Item Titles entered. This data is stored in the
node_field_data
table. - We loop through the Title values and compare them to the Title entered.
- If there is a match. We set an error using
setErrorByName()
. The user is redirected back to the node creation form, the error is displayed. - If no match. The node is created as per normal.
The code looks something like below. NOTE: In my case, the last character of the Title is random, thus compare the Title with this character removed. I use the PHP substr()
function for this.
/** * Form validate * Checks if there is a duplicate Jewellery Item Title in the database */ function check_title_exists(&$form, &$form_state) { // Remove the last character from the string $title_entered = substr($form_state->getValue('title')[0]['value'], 0, -1); $title_compared = ''; $db = \Drupal::database(); $results = $db->select('node_field_data', 'n') ->fields('n', ['title']) ->condition('n.type', 'my_content_type') ->execute(); foreach ($results as $record) { $title_compared = substr($record->title, 0, -1); if ($title_compared === $title_entered) { $form_state->setErrorByName('title', t('The Item with Title of ' . $title_entered . ' already exists.')); } } }
Comments
Wrongs solution
Instead of loading all the title and looping them through the provided one, you can directly add condition for the provided title. So that it will return the available node data.
Thank you, yes
Thank you, @Goutham, your suggestion is most appreciated.
Add new comment