0

I'm working on a Drupal 8.6 multisite and my client wants to be able to duplicate content between many of these sites. The codebase of the websites is the same, but each of them uses a different database. For that, I made a module with some hooks that gets the node serialized and posts it to another site. code below:

function a8_replicate_node_insert(Node $node) {
  $type = $node->getType();

  if($type == 'event')
  {
    $portals = $node->get('field_duplicate_to_portal')->getValue();
    $serializer = \Drupal::service('serializer');
    $data = $serializer->serialize($node, 'json', ['plugin_id' => 'entity']);
    $data = json_decode($data); // make it array again

    foreach ($portals as $url) {
      try{
        a8_replicate_post_to_other_site($url['value'], $data, 'insert');
      }
      catch (\Exception $e){
        die($e->getMessage());
      }
    }

  }
}

The a8_replicate_post_to_other_site function just uses curl to post the data as json to the other website. Then I made another module to receive the content, with the following function:

  public function receive() {
    $ip = \Drupal::request()->getClientIp();
    // to make sure it's the machine posting to itself
    if($ip == '127.0.0.1') {
      $data = json_decode(file_get_contents('php://input'), true);

      if($data['action']=='insert') {

        $node = Node::create($data['node']);
        $node->save();// <<<< error happens here 
      }
    }
  }

It's my first Drupal development and I'm I don't know pretty well what I'm doing.

Is this the right way to create a node? Is there a better and safer way to do it?

1

I wouldn't use the approach you used. Here is my recommendation.

First, define your database connection to each multisite on the default setting.php with different name, check the example below:

#Default site 

$databases['default']['default'] = array (
  'database' => 'dbname',
  'username' => 'uname',
  'password' => 'password',
  'prefix' => '',
  'host' => 'host',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

#Site 1
$databases['site1']['default'] = array (
  'database' => 'dbname',
  'username' => 'uname',
  'password' => 'password',
  'prefix' => '',
  'host' => 'host',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);

#Site 2
$databases['site2']['default'] = array (
  'database' => 'dbname',
  'username' => 'uname',
  'password' => 'password',
  'prefix' => '',
  'host' => 'host',
  'port' => '3306',
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);


Now, on hook_node_insert you can save the node object to multiple databases by changing the database each time, refer the code below as an example:

// Switch to site 1 database 
\Drupal\Core\Database\Database::setActiveConnection('site1');
//$node will have all fields you need 
$site1Node = Node::create([
    'type'        => $node->getType();,
    'title'       => $node->getTitle();,
    'body_text'   => $node->get('body')->value,
]);
$site1Node->save();
// Switch to site 2 database 
\Drupal\Core\Database\Database::setActiveConnection('site2');

$site2Node = Node::create([
    'type'        => $node->getType();,
    'title'       => $node->getTitle();,
    'body_text'   => $node->get('body')->value,
]);
$site2Node->save();

// finnally make sure to swich back to default datyabase 
\Drupal\Core\Database\Database::setActiveConnection();
|improve this answer|||||
  • I like your approach. What about all the other properties and relationships? – André Luiz Aug 21 '19 at 13:49
  • Should I use a 'use' sentence for the database switch to work? I'm doing it but it's not switching the database – André Luiz Aug 21 '19 at 14:24
  • The database switching class is using the full namespace to call the function, Probably you will need to add Node namespace `` use Drupal\node\Entity\Node; `` Also, please feel free to share your code too. – Hunde Tekle Aug 21 '19 at 17:05
0

Don't reinvent the wheel. Have you had a look at either of these modules that are both feature rich and accomplish the objective?

https://www.drupal.org/project/content_sync

https://www.drupal.org/project/entity_pilot

|improve this answer|||||
  • Have you ever had this message when trying to use content sync? "The drush command 'content-sync:export' could not be found." I refreshed the cache and nothing changes – André Luiz Aug 21 '19 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.