0

I created a custom D8 module in:

<root>/modules/custom/mymodule 

In that custom module are src/Controller/MyController.php and src/EventSubscriber/MySubscriber.php.

I wrote some custom code in my custom theme in <root>/themes/mytheme/src/MyClass.php.

My namespaces are: Drupal\mymodule and Drupal\mytheme.

I can add/use MyClass in MySubscriber.php (use Drupal\mytheme\MyClass) and it works fine.

However, when trying to add MyClass to MyController.php, it creates a PHP error claiming that it cannot find MyClass. The MyClass code is identical between the two module files.

Why won't it work in MyController.php while working fine in MySubscriber.php?

I've tried a lot of testing, resetting the cache, etc., but cannot find a reason for this. I can use Drupal core classes in myController.php, but nothing from the themes directory (I tried to include custom code from another custom theme).

Any hints? Any best-practice work-arounds?

2

I never tried accessing theme classes from within any module classes. The reason is simple: The best practice you asked for is not doing so.

Whereas you can add classes to a theme for theming using object-oriented code, you should limit the operations performed by the theme to manipulating output generated by Drupal core and modules.

This should happen in a manner that allows for easily replacing your theme by another theme which is not featuring these classes.

Making a module dependent in a theme class will break this functionality.

Without having screened the core of Drupal, I could imagine that autoloading theme classes won't take place before theme negotiation happened.

Consider moving whatever your theme class does and is required by your module to a custom service provided by your module instead of the theme.

EDIT:

According to your comment, your original theme class had the use of creating a data table that should be themed for output.

The "Drupal way" then would be to moving your class to your custom module and making it a service by creating an according mymodule.services.yml (read more about creating a custom service here or here):

services:
  mymodule.myclass:
    class: Drupal\mymodule\MyClass

Then you can create an instance of your service by either using dependency injection (within the scope of other classes as your controller and/or event subscribers), or the static \Drupal::service('mymodule.myclass') getter within procedural *.module and *.theme files.

Your service could either have a method that returns the data table only, or even have a method for returning a themed version of the data table (render array with a #theme wrapper), whereas you implement a custom hook_theme() with a template and/or pre-processing from within your module.

  • Thank you for your reply. I agree with and try to follow the principles you bring up. I did try to move MyClass in to the module /src dir (and updated namespace), but it didn't load either. More generally, Drupal has always separated MVC in to two places (MC in modules, V in themes) which makes it difficult to create a cohesive product that renders and functions well while doing it the "Drupal way." I understand the intent of modularity and separating the view from function, but what good is generating a data table for a user if there's no theme/view to support it? – Jon Paul Vivere Jan 11 '18 at 13:56
  • As mentioned before: Try providing re-usable code within a service (drupal.org/docs/8/api/services-and-dependency-injection/…), e.g. if you want to create the data table in your module and your theme. Additionally, you can always implement hook_theme() within your module, provide a default template, and wrap your data table in a generic template provided by your module. Then your and any other theme can optionally override this template and add additional visual features to your data table. – Mario Steinitz Jan 11 '18 at 14:04
  • @JonPaulVivere: I updated my answer accordingly. – Mario Steinitz Jan 11 '18 at 14:37
  • The only theme I have seen with OO code in it was the Bootstrap theme, but I don't believe that code has ever been accessed outside of the theme by the system at large. That said, it's probably not a great idea to have OO code in the theme that is depended upon by the system at large. – Kevin Jan 11 '18 at 14:42
  • @Mario Thank you for your helpful advice and references. After some more hammering and moving MyClass (and its interfaces) inside the module, I was able to get it working. I'll make another effort in deploying everything inside the module. Thanks again! – Jon Paul Vivere Jan 11 '18 at 15:16

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.