I have a Drupal 8 custom module that contains 5K of php in 10 classes. This code is production ready for the launch of a new website.

I also have code that runs from non-drush shell scripts. One example is the creation and distribution of a newsletter that runs from crontab. This pulls data from Drupal and creates a multi-part (html & plain text) email in multiple languages.

There is overlap between these two sets of code that would like to eliminate. How can I create a single php code library that can be shared between Drupal 8 and also used in standalone shell scripts?

There seems to be two approaches here:

(1) place all code in the custom module and Include it in shell scripts

I understand how to accomplish the custom module part of this. I don't know how to do the include into a stand-alone shell script from the Drupal directory.

(2) place all code in an external library and Include it in the custom module, the shell scripts and anywhere else I need it

This approach seems to have more flexibility. It addresses my original issue of sharing code between Drupal custom modules and stand-along scripts. It also allows the same code to be used in multiple projects -- separate Drupal 8 installs perhaps for difference clients.

How can I pull a custom php library (not on packalist.org) into my Drupal custom module? If this is possible, I will likely move most/all of my Drupal and Shell Script PHP code to a common external library that is under github change control.

  • It does sound though as if your stand-alone code, is not really stand-alone, since it needs access to Drupal's data layer; in that case, case (1) does have practical value as it allows you to tap into Drupal in the easiest possible way by simply running your stand alone PHP-CLI scripts via drush scr. On a different note, if your code is meant to be reused across different client projects, then it really has to be generic; otherwise the value of setting it up as a independent library dependency is very minimal. Apr 22 '18 at 8:39
  • I agree 100%! Now that I have approach (2) working, I can structure my code to take advantage of it. I was never motivated until Now!
    – Greg Sims
    Apr 22 '18 at 20:53

It's possible to pull custom php libraries into your project with composer. You'll need to define the repository in the repositories section. Checkout handling private packages and repositories in composer's documentation. It's really fairly easy. If you have a single github repo you can include the repository info like below:

"repositories": [
    {"type": "composer", "url": "https://packages.drupal.org/8"},
    {"type": "vcs", "url": "https://github.com/myorg/mypackage"}

You should include a composer.json file in your repo as you'd probably expect. Here is a simple one to get you started:

    "name": "myorg/mypackage",
    "description": "My Package is the greatest!",
    "license": "proprietary",

    "autoload": {
        "psr-4": {"Myorg\\Mypackage\\": "src/"}

Now your code can by placed in scr/Myclass.php with a

namespace Myorg\Mypackage;

Class Myclass {}

Choosing which version to pull in is a little but confusing. When you include a branch you need to prefix the branch nave with dev-, e.g. dev-master for the master branch. Otherwise, you can create tags and pull them in by their name, e.g. 1.0.0, etc. I've used this technique successfully with bitbucket.

Some inclusion examples where your composer.json in your repo defines your package name as myorg/mypackage:

// This will pull whichever branch is marked as the "default" branch in your repo
composer require myorg/mypackage

// This will pull the "develop" branch
composer require myorg/mypackage:dev-develop

// This will pull in the "2.1.3" tag
composer require myorg/mypackage:2.1.3

// You can also use "^" and "~" with tags
composer require myorg/mypackage:^2.1.0

You can tell composer where to put your package by adding a new item to the extra.installer-paths section of composer.json. For example, if you want to install your package to web/modules/custom add a line like:

"extra": {
    "installer-paths": {
        "web/modules/custom/{$name}": ["vendor:myorg"],
        "web/core": ["type:drupal-core"],

If your repos are private, you may have some issues pulling your repo as a package. I've worked around this issue by using my ssh key for access to the repos and making sure anyone who runs composer require myorg/mypackage also uses the ssh key method.

An alternate technique is to create a zip release of your package and include it as a repository as the chosen module's README explains.

  • Is the namespace update to your github file also appearing in the file in your vendor directory? If you made the update after doing composer update, you'll need to make sure to composer update RayStedman/rsm to pull the change.
    – sonfd
    Apr 22 '18 at 3:11
  • I think you should ask a new question for this separate issue. I'm not sure what the problem is here, maybe the autoloader doesn't know about your class for some reason. Maybe this other issue can help.
    – sonfd
    Apr 22 '18 at 15:06

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.