Drupal News

Aten Design Group: Programmatically copy field data in Drupal 8

Main Drupal Feed - Tue, 06/22/2021 - 15:54
Programmatically copy field data in Drupal 8 John Ferris Tue, 06/22/2021 - 09:54 Drupal Drupal 8 Code

The code to programmatically copy field data in Drupal 8 is pretty simple, but I wasn’t able to find any great examples for performing the operation at scale when I ran into the need myself. Hopefully the code sample below helps somebody save a few minutes of digging for solutions.

My use case was straightforward: After more than a year of continual development on a client site, new patterns emerged in how content editors utilized certain entity reference fields. It became apparent that similar relationships across different content types used separate fields with different machine names. This made it tricky to aggregate and filter content. It also led to overly complex implementations of any custom functionality based on these relationships. One thing was clear: we needed the fields to be consistent across content types.

Basically, I needed entity references stored in various older fields, let’s say field_old_one and field_old_two, to be copied into a single destination field we’ll call field_new.

Once I’d added our field_new field to all the appropriate content types via the field UI, I needed to migrate the references out of the old fields, and into the new fields. What’s the best way to do this when manual GUI changes would take too long? A hook_post_update_NAME implementation was my answer.

The code to programmatically copy field data in Drupal 8 isn’t the hard part. Assuming your source and destination field types are compatible, it’s just two quick lines:

/* @var $node \Drupal\node\NodeInterface $node */ $node->$dest_field = $node->$source_field; $node->save();

It gets complicated when you need to do this on hundreds or thousands of entities. We don’t want to load, process, and save all those entities at once as that would likely bring our server down. We need to batch the operation. Implementations of hook_post_update_NAME act as implementations of callback_batch_operation — allowing us to execute a custom callback _my_module_copy_field_values across multiple HTTP requests and avoid PHP timeouts. First, we define that callback.

/** * Copies the value from one field to another empty field. * * @param array $sandbox * The batch operation sandbox. * @param string $bundle * The node bundle. * @param string $source_field * The source field name. * @param string $dest_field * The destination field. * @param int $nodes_per_batch * The amount of nodes to update at a given time. */ function _my_module_copy_field_values(array &$sandbox, $bundle, $source_field, $dest_field, $nodes_per_batch = 20) { $storage = \Drupal::entityTypeManager()->getStorage('node'); // Initialize some variables during the first pass through. if (!isset($sandbox['total'])) { $query = $storage->getQuery() ->condition('type', $bundle) ->notExists($dest_field) ->exists($source_field) ->accessCheck(FALSE);   $nids = $query->execute();   $sandbox['total'] = count($nids); $sandbox['ids'] = array_chunk($nids, $nodes_per_batch); $sandbox['current'] = 0; }   if ($sandbox['total'] == 0) { $sandbox['#finished'] = 1; return; }   $nids = array_shift($sandbox['ids']); $nodes = $storage->loadMultiple($nids);   /* @var $node \Drupal\node\NodeInterface $node */ foreach ($nodes as $node) { $node->$dest_field = $node->$source_field; // Programmatically copy field data $node->save(); $sandbox['current']++; }   $sandbox['#finished'] = min(($sandbox['current'] / $sandbox['total']), 1); }

In this case, the $sandbox variable is passed by reference to each iteration of the post_update hook. It will loop over this function until $sandbox['#finished'] == 1 — or until the current node operation is equal to the total number of nodes.

In my case, I needed to run this operation on a few different fields across half a dozen content types each with their own mappings — I’ll just use article and post in my example below. To make it a little easier, I wrote the custom callback _my_module_copy_field_values to apply updates on a per content type and field basis. Then I called it from a few implementations of hook_post_update_NAME, one for each content type.

With your custom callback _my_module_copy_field_values defined, you simply call it in your hook_post_update_NAME implementations defined in your MY_MODULE.post_update.php file. Then when you run database updates, your work is done.

/** * Migrate Article field_old_one > field_new. */ function my_module_post_update_8001_migrate_alert_department(&$sandbox) { _my_module_copy_field_values($sandbox, 'article', 'field_old_one', 'field_new'); } /** * Migrate Post field_old_two > field_new. */ function my_module_post_update_8002_migrate_service_department(&$sandbox) { _my_module_copy_field_values($sandbox, 'post', 'field_old_two', 'field_new'); }

Executing your field level changes in hook_post_update_NAME versus hook_update ensures that any schema level changes (which should be in hook_update) are completed before your content level changes — just in case you’ve got some other updates going on or are working with a handful of other developers in the same codebase.

Do you have a simpler way to do this? Feel free to share in the comments.

John Ferris

Tag1 Consulting: Does your content speak for itself? A fireside chat with Preston So, author of Voice Content and Usability - Part 1

Main Drupal Feed - Tue, 06/22/2021 - 14:00

For thousands of years, much of the content that fills our books and today lines our websites has been rooted in the written word. But in recent decades, voice interfaces have grown in both performance and popularity as users begin to seek novel ways to access information, especially through the uniquely human medium of spoken content. How do we adjust to the new paradigm of voice content—copy and media conveyed through sound—when our content strategy and design approaches remain moored in visual experiences?

Read more lynette@tag1co… Tue, 06/22/2021 - 07:00

Ben's SEO Blog: The XML Sitemap Module

Main Drupal Feed - Tue, 06/22/2021 - 13:32
The XML Sitemap Module Having an XML sitemap gives Google a list of the pages that you wish them to crawl. While they can crawl your site without it, large & complex sites confuse the crawler so it could potentially miss pages and even whole sections. Tracy Cooper Tue, 06/22/2021 - 08:32

Specbee: How to Discipline your Code with Refactoring (Includes PHP examples)

Main Drupal Feed - Tue, 06/22/2021 - 11:04
How to Discipline your Code with Refactoring (Includes PHP examples) Pradosh 22 Jun, 2021 Top 10 best practices for designing a perfect UX for your mobile app

Like many other things in life, our code needs some discipline too. I’m pretty sure no developer in the world wants to write unclean code. However, unclean code still does exist. It can arise due to various reasons - may be due to business pressure, lack of documentation, lack of interaction among team members or incompetence of the developer. Due action needs to be taken to make the code cleaner and to avoid problems that may come up in the future because of this. Fortunately, we can tackle these issues with a disciplined technique to restructure the code called as Refactoring.

Refactoring is a technique to improve the internal structure of the existing program source code and maintaining its external behavior. It is a step-by-step procedure to improve the code, which will otherwise cost us a lot of time and effort.

Disadvantages of Unclean Code

Expanding the source code size by adding new programs to it without refactoring for a long time makes the code messy and unclean. It makes the maintenance and further development on the project very difficult. Unclean code comes with tons of disadvantages:

  1. It increases the maintenance cost of the project.
  2. Adding new feature takes a lot of time and sometimes it become impossible to add.
  3. It slows down the introduction of new people to the project.
  4. It contains duplicate code.
  5. It does not pass all tests.

There are many other disadvantages, but these problems cost a lot of money and time to the organization.

Advantages of Clean Code

Clean and disciplined code has its own advantages:

  1. It does not contain duplicate code.
  2. It passes all tests.
  3. Makes the code more readable and easier to comprehend.
  4. It makes the code easier to maintain and less expensive.

Advantages of clean code are many. The process of turning a messy unclean code into a more maintainable clean code is called Refactoring process.

Refactoring Process

Refactoring should be done as a series of small changes, each of which slightly improves the existing code and allows the program to continue to run without breaking it. After refactoring, code should become cleaner than before. If it remains unclean, then there is no point of refactoring. It is just a loss of time and effort. No new code should be added during refactoring to create new functionality. It should pass all the tests after refactoring.

When to Refactor

Refactoring should be performed when:

  • Adding duplicate code to the project. Because duplicate code is hard to maintain and changes in one place may require updates in many other places.
  • Adding a feature. Refactoring makes it easier to add new functionality.
  • When fixing a bug, you should refactor because it will make the bug discovered automatically.
  • Code review is the last stage of refactoring the code before changes are deployed to production.
Dealing with Code Smells

Problems on the code are sometimes referred to as code smells. These are the problems addressed during the refactoring. They are easier to find and fix.

For example:

  • Large methods and classes which are very hard to work with.
  • Incomplete or incorrect usage of object-oriented programming concept.
  • Code that makes it hard to add any changes.
  • Duplicate and deprecated code in the project.
  • Highly coupled code.
Refactoring Techniques

Refactoring techniques are the steps taken to refactor the code. Some of the refactoring techniques are:

1. The Extract Method

// Problem

function printInvoice() {     $this->printHeader();        // Print details.     print("name:  " . $this->name);     print("amount " . $this->getPrice()); }

// Solution

function printInvoice() {     $this->printBanner();     $this->printDetails($this->getPrice()); }    function printDetails($price) {     print("name:  " . $this->name);     print("amount " . $outstanding); }

If you have a code fragment that can be grouped, add a new method for that part of code and replace the old code. It makes the code more isolated and removes duplication.

2. Extract Variable

// Problem

if (($student->getMarksinMath() > 60) &&     ($student->getMarksInPhysics() > 60) &&     ($student->getMarksinChemistry() > 60) && $this->pass) {   // do something }

// Solution

$mathResult = $student->getMarksinMath() > 60; $physicsResult = $student->getMarksinPhysics() > 60; $chemistryResult = $student->getMarksinChemistry() > 60; $hasPassed = $this->pass; if ($mathResult && $physicsResult && $chemistryResult && $hasPassed) {   // do something }

For large expressions like the one displayed in the problem, which is very hard to understand, different variables can be created for each expression. It makes the code more readable. But this method should be applied with caution. However, it has its own disadvantages. The code will execute even if the condition is false which is not the case in the problem.

3. The Inline Method

// Problem

function printResult() {     return ($this->getResult()) ? “Pass” : “Fail”; } function getResult() {     return $this->totalMarks > 300; }

// Solution

function getRating() {     return ($this->totalMarks > 300) ? “Pass” : “Fail”; }

When the method body is more obvious, use this technique. Replace the method with method content and delete the method. It minimizes the number of unwanted methods.

4. Inline Temp

// Problem

$mathMark = $student->getMathResult(); return $mathMark > 60;

// Solution

return $student->getMathResult() > 60;

If there is an unwanted temporary variable which just holds the expression result, remove the variable with the expression itself. It helps in getting rid of unnecessary variables.

5. Replace array with object

// Problem

$row = []; $row[0] = "Virat Kohli"; $row[1] = 70;

// Solution

$row = new Player(); $row->setName("Virat Kohli"); $row->setNumberofCentury(70);

If there is an array with various types of data, replace that with an object. Because fields of a class are easier to document and maintain than arrays with various types of data.

6. Parameterized Method

// Problem

function fivePercentRaise() { } function tenPercentRaise() {    }

// Solution

function raise(percent) { }

If multiple methods perform similar action on data, then replace all the methods with one method and pass the data as argument(s). It removes duplicate and redundant methods.

7. Separate query from modifier

// Problem

function getInterest() {     $this->interestAmount = $this->principal * 10 / 100;     return $this->interestAmount; }

// Solution

function setInterest() {     $this->interestAmount = $this->principal * 10 / 100; } function getInterest() {     return $this->interestAmount; }

If a method is returning value and changing the object, split the two methods. One for modification and another to return the result. It removes the chance of unintentional modification of an object.

Unclean and chaotic code leads to technical debt that keeps adding up if not tackled right. And a debt always means a loss. Refactoring the code is a technique that can help fight issues that leads to bad and smelly code. Need help or more information on refactoring your code? Contact Specbee’s specialists today!

Drupal Development Drupal Planet Web Development Coding Shefali ShettyApr 05, 2017 Subscribe For Our Newsletter And Stay Updated Subscribe

Leave us a Comment

  Shefali ShettyApr 05, 2017 Recent Posts Image How to Discipline your Code with Refactoring (Includes PHP examples) Image Top 10 Things you need to know about CSS Grid Layouts Image Building (more) Secure Drupal Websites with the Password Policy Module Want to extract the maximum out of Drupal? TALK TO US Featured Success Stories

A Drupal powered multi-site, multi-lingual platform to enable a unified user experience at SEMI.


Discover how our technology enabled UX Magazine to cater to their massive audience and launch outreach programs.


Discover how a Drupal powered internal portal encouraged the sellers at Flipkart to obtain the latest insights with respect to a particular domain.


Jacob Rockowitz: How should we encourage organizations to sponsor the Webform module's Open Collective?

Main Drupal Feed - Mon, 06/21/2021 - 21:40

In January 2021, I started writing about my work situation. As that aspect of my life (and my blog) evolved, I gradually started focusing on improving the sustainability of the Webform module for Drupal. Last month, I began expensing the Webform module's maintenance to the Webform module's Open Collective. Getting compensated for my time has been a great experience, and I am very grateful to the backers of the Webform module's Open Collective.

To my delight, with each blog post, more and more individuals and some organizations are becoming backers of the Webform module's Open Collective. Why individuals would want to help support the Webform module makes perfect sense to me. Individuals generally have some immediate understanding of the benefits of the Webform module or the challenge of maintaining an open source project or contribution. This is why I back Drupal's Simplytest.me, Drupal Recording Initiative, and the Gin Admin Theme collectives. One of the patterns I’ve noticed in the open source community, the Drupal community, and in Open Collectives is that individuals tend to understand and appreciate both the inherent value of open source and the need to contribute. Alternatively, organizations don't always see the value and need of helping, contributing to, and supporting the open source software they use to build and maintain their businesses.

Why do we need to get more organizations involved?

To my mind, it’s crucial to get more organizations involved for two reasons: First, organizations generally gain more financial resources from open source, either using it for their business or offering it as a service to their clients...Read More

Web Omelette: <p>In this article I present a short

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I present a short extract from my book Drupal 9 Module Development. The topic: menu system and types of menu links.

Web Omelette: <p>In this short article I introduce a

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this short article I introduce a new Drupal module that allows you to define Ajax-based multi-value form elements.

Web Omelette: <p>In this article I am going to show

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I am going to show you a neat little trick for having Ajax powered buttons rendered inside a table form.

Web Omelette: <p>In this article I introduce the

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I introduce the Composite Reference Drupal module that can be used for parent-child entity relations that are supposed to live (and die) together.

Web Omelette: <p>In this excerpt from the book Drupal

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this excerpt from the book Drupal 8 Module Development, I introduce the TypedData API.

Web Omelette: <p>In this excerpt from the book Drupal

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this excerpt from the book Drupal 8 Module Development, I introduce automated testing in Drupal.

Web Omelette: <p>In this article I am going to

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I am going to quickly show you a neat little addition to the migrate Entity destination that runs validation on entities before saving them.

Web Omelette: <p>In this article I am going to show

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I am going to show you a quick trick to speed up the generation of the CSV source plugin configuration for large CSV files when doing Drupal migrations.

Web Omelette: <p>In this article I am going to show

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I am going to show you how to build dynamic migrations that depend on the state of your system by using (migration) plugin derivatives.

Web Omelette: <p>In this article I am going to show

Main Drupal Feed - Mon, 06/21/2021 - 16:54

In this article I am going to show you the power of using Drupal 8 filters to render your basic markup in a way compliant with various frontend frameworks like Bootstrap.

Skvare.com: Training Video: Doing More with Views, Calendars & Maps

Main Drupal Feed - Mon, 06/21/2021 - 15:29
Training Video: Doing More with Views, Calendars & Maps

Watch Part 3 of our CiviCRM Entity training series.

Gena Dellett Mon, 06/21/2021 - 10:29

Agiledrop.com Blog: Why outsourcing is the way to go for times of uncertainty

Main Drupal Feed - Mon, 06/21/2021 - 05:20

In this article, we look into why outsourcing is so well suited for times of uncertainty and how businesses can benefit from it.


#! code: Drupal 9: Changing Config Through Update Hooks

Main Drupal Feed - Sun, 06/20/2021 - 21:39

Drupal configuration is normally changed or removed through the configuration import and export process. For example, the process I follow is to make the change in the configuration locally, export the configuration into the source code, deploy the source code to a remote server and import the configuration. Using this mechanism, configuration changes that were exported locally are imported into the site and are ready to use.

There are certain situations where using update hooks to update the configuration is necessary. This means that you would change the configuration in your system directly using code in update hooks, rather than following the export and import process. These situations are rare, but necessary from time to time in order to maintain a consistent configuration on your site.

Key to all of this is to always run your update hooks before performing your configuration import. This is important rule to follow as the Drupal update process can alter or tweak the fields and tables that contain Drupal configuration entities. Then, when importing the Drupal configuration the data structure is in the correct state and is ready to accept the changes.

Let's look at a few of the situations that you might encounter and how to approach each of them using update hooks.

Updating Configuration Splits

If you are using configuration splits to manage your different environments then you will encounter an issue where you import your configuration and then realise you need to import the configuration again.

Read more.

Third & Grove: Issue Queue Analysis by TAG's Drupal Core Contributor

Main Drupal Feed - Sun, 06/20/2021 - 10:27

I decided to look at the Drupal core issue queue to understand better how many issues are open and the direction things are going. The results were a bit of a shock.

First, let's get the shock out of the way, then let's take a look at what's happening, and finally, what we can do to change things.

Drupal Atlanta Medium Publication: Configuration Split in Drupal 8 and 9. How to Add Config To Your Live Environment

Main Drupal Feed - Sat, 06/19/2021 - 18:15
How do enable that module for just the live site again?

Let’s first start off with understanding what the Configuration Split module does. In simple terms, it allows you to have different site configurations for your different environments. For example, you want to turn off the Views UI module on your live site. Or you want to turn off your Google Analytics module on your local, dev, and test environments but still have it active on your live site.

There are so many great articles on setting up configuration split. Here are a few good ones that I suggest reading to get you caught up to speed.

So how do you test and or create new configuration settings for your live environment while working on your local computer?

In other words, say that you have already set up your config-splits a few months ago but now your client wants to add email support using the SMTP module but you only want this enabled on the live site so you don’t accidentally send out an email from your local site to 1000’s of users. ps — I have done it before Ouch :)

Well in order to add to the live configuration you need to enable the live config split. The natural first step is to go to the config-split UI and disable the develop configuration and enable the live config. Click Click Click. But nothing. Such a simple thing but why in the heck are you not able to enable the live configuration?

Ohhh snap, that settings.php file got me again.The settings.php Environment Gotcha

One thing all of these tutorials have in common is that they show you how to set the active and inactive config-splits in your settings.php. For some servers, the code is slightly different but the idea here is that Drupal needs to somehow know what environment you are on in order to import the right configuration.

Yep! That darn settings.php file. The reason you cannot activate the live configuration settings in the UI is that the settings.php file overrides the UI click clicks. So you need to go to your file and either temporarily comment out that code or just reverse the logic. So here is what I do.

  1. Reverse the logic in the settings.php file. For me, I just have to switch out a ! in my code so that my dev and live environments are reversed.
  2. drush cr — Cache rules everything around me — Clear it
  3. Enable my new SMPT module.
  4. Edit the live config split and check the box next to live
  5. drush cex — configuration export
  6. git checkout settings.php so that my file revers back to my old settings
  7. drush cr— you know the drill clear that cache
  8. Uninstall the SMTP module
  9. drush cex — to export the uninstalled module settings to your dev config
  10. git commit my changes

I then check my setting by doing a drush csim live. This command imports the settings from the live config. You can also check your config directories manually or with a git statusto ensure there are new files in both of your dev and live directories.

If any of you have a better way to enable and add some new configuration to the live environment without all of the steps, help a brother out and let me know in the comments.

Configuration Split in Drupal 8 and 9. How to Add Config To Your Live Environment was originally published in Drupal Atlanta on Medium, where people are continuing the conversation by highlighting and responding to this story.