4

I'm working on a module which will require a library that is already in composer.

I added a line to my module's composer.json file:

"require": {
   "markrogoyski/math-php" : "dev-master"
}

I ran the command:

composer update .

and a "vendor" directory was created in my module's directory and the files were downloaded. However, If I add a use statement to the file my_module/src/Controller/Test.php I get an error:

----Test.php----

<?php
namespace Drupal\lims\Controller;

use Drupal\Core\Controller\ControllerBase;
use Math\Functions\Map\Single;

class Sample extends ControllerBase {
    public function content() {
        print_r(Single::square([1,2,3,4,5]));
    }
}

I see the error:

PHP Fatal error:  Class 'Math\\Functions\\Map\\Single' not found in [module path]/src/Controller/Test.php on line 9

Is there another step that I need to do to get the library autoloaded in the correct namespace?

0

4 Answers 4

7

Using composer update, Composer created the vendor directory, and the autoload.php file, which is necessary to autoload the library. Unfortunately, Drupal doesn't load all the autoload.php files found in each of the directories containing a module.

Instead of adding the dependency of your module in the composer.json file used by Drupal, you should edit its extra/merge-plugin section to include the directory containing the modules you add. (I added the "modules/*/composer.json" line.)

"extra": {
    "_readme": [
        "By default Drupal loads the autoloader from ./vendor/autoload.php.",
        "To change the autoloader you can edit ./autoload.php."
    ],
    "merge-plugin": {
        "include": [
            "core/composer.json",
            "modules/*/composer.json"
        ],
        "recurse": false,
        "replace": false,
        "merge-extra": false
    }
},

In this way, running composer update from the Drupal root directory would add the required classes in the vendor directory used by Drupal, making them automatically loaded.

If the modules you install are all hosted on drupal.org (i.e., you don't use any custom module), you can instead edit the repositories section to contain the following lines.

"repositories": {
    "drupal": {
        "type": "composer",
        "url": "https://packagist.drupal-composer.org"
    }
}

In this way, you could add a module hosted on drupal.org running composer require drupal/module-name from the Drupal root directory, and Composer would install its dependencies (declared in the module's composer.json file) in the vendor directory, making the classes automatically loaded.

5
  • 1
    There is also mile23/drupal-merge-plugin for helping with this. And if he module is hosed on drupal.org, then the composer.json of the module does not need any of that. And you can add the drupal.org composer repository https://packagist.drupal.org/8. Then a composer require drupal/module-name will work fine. Otherwise, the merge-plugin strategy above comes into play.
    – mradcliffe
    Commented Aug 22, 2016 at 22:49
  • I should have been clearer: I am not saying to do both, but either one or the other, depending on where the modules are hosted.
    – avpaderno
    Commented Aug 23, 2016 at 6:28
  • Also, that plugin doesn't even have releases on packagist.org. I would rather not use it.
    – avpaderno
    Commented Aug 23, 2016 at 6:33
  • Which "that plugin"? This exists for drupal-merge-plugin: packagist.org/packages/mile23/drupal-merge-plugin?
    – mradcliffe
    Commented Aug 23, 2016 at 15:03
  • I see only a dev-master branch, for drupal-merge-plugin; there aren't versions.
    – avpaderno
    Commented Mar 10, 2017 at 12:02
2

Presuming you use the Composer template for Drupal projects:

  1. In your custom module run composer init and then require a package/library.
  2. In your Drupal project run composer require wikimedia/composer-merge-plugin.

    Then add the following to the "extra" array in your Drupal project's composer.json:

    "merge-plugin": {
        "include": [
            "web/modules/custom/*/composer.json"
        ]
    }
    

    (See docs on DO: MergePlugin.php.)

    (See composer-merge-plugin on GitHub.)

  3. In your Drupal project run composer update.

    That's it.

1
  • Thanks @leymannx, your solution works for me!
    – aserww106
    Commented May 28, 2019 at 17:40
-1

As per the documentation you will need to use the dump-autoload command to recreate the autoloader file.

3
  • I ran that command in the module root directory, and the response is: "Generating autoload files", and the file was still not found. I then tried running it in the Drupal Root directory, where the response was: "Generating autoload files > Drupal\Core\Composer\Composer::preAutoloadDump > Drupal\Core\Composer\Composer::ensureHtaccess" and it also did not change anything. I cleared the Drupal cache each time. Commented Aug 22, 2016 at 16:41
  • You need to run the composer install/update/dump commands in the drupal installation root.
    – Eyal
    Commented Aug 22, 2016 at 16:45
  • I got it to work by adding the require line to the drupal root composer.json file. Is there a way to add it to my module's file, and make Drupal know it's there and handle the dependency itself? Commented Aug 22, 2016 at 18:30
-1

You used well composer! The official MathPHP documentation says that you should use it like this:

use MathPHP\Functions\Map;
$x = [1,2,3,4];
$x² = Map\Single::square($x); // [1, 4, 9, 16]

Then you should not have trouble calling it from your controller. Try using "TestController.php" as filename and "TestController" as the class name. Helps the namespace.

I always use external libraries, oriented to DDD. You can see my repository.

1
  • I am one of the developers of MathPHP. The root namespace was changed from Math to MathPHP at some point between now and when I asked the question. Commented Aug 31, 2017 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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