Score:1

How can I bootstrap my site from an external script?

cn flag

Community asked.. Please clarify your specific problem...

Fair comment. What I'd like help with is how do I correct the script below so it works with D9.

<?php


use Drupal\Core\DrupalKernel;

$autoloader = require_once 'autoload.php';

// This next line is the problem
$request = Request::createFromGlobals();


$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');

$kernel->boot();

require_once 'core/includes/database.inc';
require_once 'core/includes/schema.inc';


$em = $kernel->getContainer()->get('entity_type.manager');

$entity = $em->getStorage('node')->create(array(

    'type'        => 'article',
    'title'       => 'Druplicon test',
    
 ));       


$entity->save();

?>

This is the same as the D8 script below which works - except I have:

  • removed the use symphony line;
  • replaced the deprecated function ( thanks leymannx )

The script fails as noted on the line
$request = Request::createFromGlobals(); with messages

chrome-error://chromewebdata/:1 Failed to load resource: the server responded with a status of 500 () VM10:7288 crbug/1173575, non-JS module files deprecated.

Can someone point out what's wrong with this line in D9 (which I guess relates to the removal of the symphony use statement) and also if there are any other lines of code following which D9 won't like.

Thanks for any further help on this and apologies for the earlier confusion and for still being out of my depth with D9.


Original post...

This article provides D8 code to create an entity from an external script. I'm in the same boat as the person who asked this question - wanting to convert from D7's drupal_bootstrap.

Although my requirement is D9, I thought I'd try and get a D8 script working using the above post. His application is with an entity. I'm wanting to create article entries.

Here is the code I took from the above link which is said to work..

<?php

use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;

$autoloader = require_once 'autoload.php';

$request = Request::createFromGlobals();

$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');

$kernel->boot();

require_once 'core/includes/database.inc';
require_once 'core/includes/schema.inc';

$em = $kernel->getContainer()->get('entity.manager');

$entity = $em->getStorage('node')->create(array(

    'type'        => 'article',
    'title'       => 'Druplicon test',
    
 ));       

$entity->save();

?>

This code runs and creates an entry in the node_field_data table but the article is not listed as content on the site.

I'm very much feeling my way with D8/D9 coding so please bear with me if I'm doing something silly!

Once I can get this to work, I then need to find out what changes are needed for D9 - so any help here would be good. For example the D8 code uses symphony but that's not part of D9 I believe.

Thanks for any help on this to get this to work. And to help me replace my D7 experience with D8/D9!

Sorry... This code does show up in the content - I was looking at a D9 site, not the test D8 I set up. Apologies!

But I'd still like help on what changes I need to make to this script to run under D9.

leymannx avatar
ne flag
entity.manager is deprecated use entity_type.manager instead.
in flag
_"create an entity from an external script"_ - what would be the reason for doing this?
cn flag
Thanks for noting the deprecated function. Creating entities via external script is one way to synchronise Drupal with another system - e.g. a MS Access database. Seems simpler than using Services.
Kevin avatar
in flag
You can "sync" data using Migrate and scheduled cron. I've done this on several projects. The benefit to this is it will handle virtually everything for you.
cn flag
Thanks Kevin - Migrate (core module) is something I know nothing about. Syncing! Sounds brilliant. I'll check it out. The cron bit is what I've used with an external script, drupal_bootstrap.
Kevin avatar
in flag
There are several examples out there. Look at Migrate Plus module.
cn flag
Thanks Kevin. This looks a substantial module. When you said several examples, did you mean using Migrate Plus or of autoloading Drupal in an external script? Using Migrate might well be the best solution - my problem is converting a D7 site which currently has about a dozen external scripts. Which is why I'd like to sort the above script for D9, if possible. If D9 just doesn't work like D7/D8 then this module might not only be the best solution, but the only one! Thanks again.
Kevin avatar
in flag
Go in the other direction, define a source for the migration. It can connect to a database, JSON/XML api, read JSON or XML data files or CSV files. Don't bother bootstrapping and trying to update random tables, it's 10x more work.
cn flag
I'm searching out all the documentation on Migrate Plus I can find. From what you've just said if I have a MySQL DB used by MS Access, I can then sync. this with a D9 entity? This would then mirror exactly what I currently do in D7 with Forena Reports ( no D9 version ) and would provide, as you say, a much better solution. Thanks again.
Score:2
cn flag

Here is the code that allows entity creation in a D9 site from a remote script - run from the same domain as the D9 site but not from the D9 root directory.

<?php
//drupal root directory
chdir('/var/www/vhosts/example.org/httpdocs/dev3');

use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;

$autoloader = require_once 'autoload.php';

$request = Request::createFromGlobals();

$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');

$kernel->boot();

require_once 'core/includes/schema.inc';

$em = $kernel->getContainer()->get('entity_type.manager');

$entity = $em->getStorage('node')->create([
  'type'        => 'article',
  'title'       => 'Druplicon test' . date("d/m/Y")." ". date("h:i:sa"),
]);

$entity->save();

?>

The clue to this code came from this article which explains the way Drupal loads a page. It says "look at index.php in the root, if you want to see how Drupal does it". About 6 lines of code!

Why didn't my earlier script, ported from D8, work? Here are some of the things I learned:

  • the line $request = Request::createFromGlobals(); which stopped the earlier script running works ok in this code;
  • there is no file database.inc in the root directory on a D9 site;
  • I changed the deprecated entity.manager to entity_type_manager as leymannx advised;
  • D9 does seem to use Symphony - it appears in index.php in release 9.2.7. But it's a later version than D8;
  • the external script should not be in the Drupal root - not even for testing - otherwise the site fires with a 404;
  • If you want to Google for information on bootstrapping, don't use Bootstrap - otherwise all you see is info. on the theme!

Getting this working means I can replace D7 external scripts with D9. I take the point kevin makes about using the migrate module but I think bootstrapping a better solution for my use cases. E.g a user adds a record to a MySQL database in Microsoft Access under program control. The code then runs an external script to add selected fields to a Drupal entity. Immediately the Access user and the web user see the same up-to-date data.

Thanks to everyone who contributed on this. I hope this post clears up the messy way I started this question.

Vishal Kumar Sahu avatar
bd flag
Are you people facing `Error: Class 'Drupal\mysql\Driver\Database\mysql\Connection' not found...` error now? Any work around?
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.