Drupal ^8.8 || ^9 - Check For Duplicate Content Based On Node Fields

Drupal 9 Check for Duplicate Content

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:

  1. Get the form id of the Jewellery Item node creation form.
  2. Within our custom module, declare the HOOK_form_alter() function.
  3. Within the HOOK_form_alter() function, declare a custom form validate function
  4. 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 see id="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.'));
    }
  }
}

Related Articles

Comments

Permalink

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.

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.