0

I have a small module that basically contains a controller and a block plugin. I cannot figure out how to include a class in both of them

The files are located in sites/all/modules/my_module. That directory contais

$ ls -R  
.:
config/  my_module.info.yml       my_module.links.menu.yml  src/
css/     my_module.libraries.yml  my_module.routing.yml

./config:
install/

./config/install:
my_module.settings.yml

./css:
hello_block-layout.css

./src:
Controller/  Plugin/  Utils.php

./src/Controller:
MyController.php*

./src/Plugin:
Block/

./src/Plugin/Block:
MyBlock.php 

The problem is the namespaces: MyController.php has namespace Drupal\my_module\Controller and MyBlock.php has namespace Drupal\my_module\Plugin\Block

I can use the class definition in Utils.php for one of the two, if I insert a require_once in the file (with the whole path, use of .. seems not to be working) AND I use the same namespace in it.

So if MyController.php starts with

<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;

require_once '/home/rdgon/public_html/sites/all/modules/my_module/src/Utils.php';

and MyBlock.php starts with

<?php
namespace Drupal\my_module\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockPluginInterface;

require_once '/home/rdgon/public_html/sites/all/modules/my_module/src/Utils.php';

and Utils.php starts with

<?php
namespace Drupal\my_module\Controller;

then the class is used by correctly by the controller. But then MyBlock.php complains about not finding the class, because the namespaces don't match.

My question: is it possible to share (include) a class definition by several components of a module? What location should I use for the shared code and what is the proper way to include it? (using the full path of the file cannot be the way to go)

thanks in advance, Ruud

5
  • You never use require or require once. You use use statement and dependency injection. Look at core Unicode class for another example. Or define it as a service. The auto loaded will figure it all out for you.
    – Kevin
    Commented Jul 12, 2017 at 12:28
  • Hi Kevin, thanks for your help. I tried using use instead, but I cannot get it to work. In the controller, I repaced the require_once with 'use Drupal\my_module\includes\Tester;', in Utils.php I changed the namespace in 'Drupal\my_module\includes'. The file contais the definition for class Tester. However, the error.log keeps saying 'Error: Class 'Drupal\\my_module\\Controller\\Drupal\\my_module\\includes\\Tester' not found in /...../modules/my_module/src/Controller/MyController.php on line 30. Any idea?
    – ruud
    Commented Jul 12, 2017 at 12:59
  • Did you clear the cache?
    – Kevin
    Commented Jul 12, 2017 at 13:04
  • Yes, I tried both running update.php and clearing the caches. I changed the namespace to Drupal\my_module, because the errorlog made clear I made another mistake. It now says 'Error: Class 'Drupal\\my_module\\Tester' not found in /..../modules/my_module/src/Controller/MyController.php on line 30'
    – ruud
    Commented Jul 12, 2017 at 13:11
  • You need to update the post with the code now because it's impossible to tell in comments.
    – Kevin
    Commented Jul 12, 2017 at 13:13

1 Answer 1

2

If you want the class declared in my_module/src/Utils.php to be made available to any PHP script, add this at the top of that script file:

use Drupal\my_module\Utils;

This of course assumes that you're following the correct PSR-4 standards for naming: make sure that mymodule/src/Utils.php exists, and contains one single class named Utils, with namespace Drupal\my_module at the top.

See PSR-4 namespaces and autoloading in Drupal 8 for a more in-depth explanation.

2
  • Thanks Kevin and Clive for helping me on this. The problem was that I had two classes in Utils.php, class Utils and class Tester. Moving the Tester class to Tester.php did the trick. I can't believe I have tried this before ;)
    – ruud
    Commented Jul 12, 2017 at 13:32
  • One class per file.
    – Kevin
    Commented Jul 12, 2017 at 15:55

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.