API page: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension...

When a module is installed, its hook_requirements() is called with $phase set to 'install'. At this point, the module has not yet been registered with the autoloader, and thus classes in the module can't be loaded.

This should be documented.

There is a workaround for this, which should probably be documented too: see http://blog.riff.org/2015_08_27_drupal_8_tip_of_the_day_autoloaded_code_...

FGM: I have updated my blog post to account for the comments in this issue.

Novice task

See comment #2 and update in #4

Comments

joachim created an issue. See original summary.

jhodgdon’s picture

Title: document that a module's classes are not available during hook_install() 'install' phase » Document that a module's classes are not available during hook_install() or hook_requirements() 'install' phase
Issue summary: View changes
Issue tags: +Novice

You're talking about hook_requirements() having a phase, not hook_install(), right? Although probably the classes are also not available during hook_install().

Proposed documentation for both hooks: add a paragraph something like this:

During installation (when $phase == 'install'), this hook will be called before the module has been registered with the autoloader, so if you need to load a class from your module, you'll need to either load the class include file directly or register the module with the autoloader. Both drupal_get_path() and module_load_include() will work; use drupal_classloader_register() to register the module.

[and we should leave out the () part in the hook_install() docs, as that only applies to hook_requirements()]

Probably a good novice task?

joachim’s picture

> You're talking about hook_requirements() having a phase, not hook_install(), right?

Sorry, my mistake. Yes, hook_requirements() and its 'install' phase.

> Although probably the classes are also not available during hook_install().

I don't know at all whether that's the case. Certainly the article I linked to doesn't mention it, which makes me suspect that in hook_install(), classes ARE available, as if they weren't, the article would probably say so.

jhodgdon’s picture

Title: Document that a module's classes are not available during hook_install() or hook_requirements() 'install' phase » Document that a module's classes are not available during hook_requirements() 'install' phase
Issue summary: View changes

OK let's only do this for hook_requirements() then.

dimaro’s picture

Assigned: Unassigned » dimaro

I'm working on it

dimaro’s picture

Status: Active » Needs review
StatusFileSize
new1.03 KB

I have included the paragraph above, but I'm not sure whether I included it in the right place, please @jhodgdon could you guide me to avoid mistakes?

Thanks!

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community

That looks right to me, thanks!

catch’s picture

Status: Reviewed & tested by the community » Needs review

Not 100% on this one. We avoid registering classes with the autoloader on purpose in case hook_requirements() prevents the module from being installed. What's the case that needed access to classes in the module that provoked this issue?

joachim’s picture

I came across this when working on Module Builder. In hook_requirements() I wanted to check that things are set up correctly, and that meant calling MB's API to check something, and that's in a class.

jhodgdon’s picture

Hm. That's a bood point in #8 though, it could leave the auto-loader in a bad state. Is there a way to un-register the autoloader afterwards? If not, maybe we should just recommend the module_load_include() method and tell people to load just the class files they need?

dimaro’s picture

What is the status of this issue?
Can I do something?
Thanks!

jhodgdon’s picture

Status: Needs review » Needs work

It seems like a more acceptable patch would just suggest people use module_load_include() to load the files they need, rather than suggesting that they register their module with the autoloader.

dimaro’s picture

Status: Needs work » Needs review
StatusFileSize
new857 bytes
new1.22 KB

I try to fix #12.
Could be a first approach?

joachim’s picture

Status: Needs review » Needs work

This looks good, except for one thing:

+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -888,6 +888,10 @@ function hook_updater_info_alter(&$updaters) {
+ * from your module, you'll need to either load the class include file directly.

either load the class, or... ?

joachim’s picture

> We avoid registering classes with the autoloader on purpose in case hook_requirements() prevents the module from being installed.

Hmm. Looks like a bug in https://api.drupal.org/api/drupal/core!includes!install.inc/function/dru... then:

   drupal_classloader_register($module, $module_list[$module]->getPath());
    if (function_exists($function)) {
      $requirements = array_merge($requirements, $function('install'));
    }

I'll file an issue.

dimaro’s picture

Status: Needs work » Needs review
StatusFileSize
new860 bytes
new900 bytes

Fix #14.

On #15 I have a doubt.
Another issue?

joachim’s picture

Status: Needs review » Needs work

Thanks! Though another glitch has crept in:

'include file' should be 'include the file'?

Also, while grammatically that works, I'm now rather confused about the PHP side of things: what is the difference between 'loading the class' and 'including the file'?

johnrosswvsu’s picture

Status: Needs work » Needs review
StatusFileSize
new864 bytes

I am updating the patch @dimaro has submitted with the fix on the issue found by @joachim.

Already did the patch against 8.2.x.

Thanks.

jhodgdon’s picture

Status: Needs review » Needs work

Thanks! Looking pretty close...

+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -888,6 +888,10 @@ function hook_updater_info_alter(&$updaters) {
+ * from your module, you'll need to either load the class or include the file
+ * directly. Both drupal_get_path() and module_load_include() will work.

Just say "... you'll need to include the class file directly". Otherwise... what does "load the class" mean?

dimaro’s picture

Status: Needs work » Needs review
StatusFileSize
new845 bytes
new892 bytes

Patch to apply changes mentioned on #20.

joachim’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.

jhodgdon’s picture

Version: 8.0.x-dev » 8.2.x-dev
Issue tags: +needs backport to 8.1.x, +needs backport to 8.0.x

Thanks! +1 for RTBC (again).

Changing version to 8.2.x to verify it applies there. Should be committed to all 3 8.x branches. Adding backport tags accordingly, although the "port" should consist of just "apply the same patch" I think.

catch’s picture

Category: Bug report » Task
Priority: Major » Normal
Status: Reviewed & tested by the community » Needs work

We're discouraging use of drupal_get_path(), for example in #2351919: Replace uses of drupal_get_path() with __DIR__ where possible. Since the classes are internal to the module, using __DIR__ would be fine.

Also downgrading from major bug since the behaviour itself is by design.

dimaro’s picture

+++ b/core/lib/Drupal/Core/Extension/module.api.php
@@ -888,6 +888,10 @@ function hook_updater_info_alter(&$updaters) {
+ * from your module, you'll need to include the class file directly. Both
+ * drupal_get_path() and module_load_include() will work.

@jhodgdon We only have to replace drupal_get_path() for __DIR__? or it needs some more work?

joachim’s picture

Category: Task » Bug report
Priority: Normal » Major

The behaviour may be by design, by the absence of documentation about it is the bug.

jhodgdon’s picture

Priority: Major » Normal

RE #26, it isn't really major.

RE #25, I think that it doesn't make sense to say "_DIR_ will work" because that is a PHP function so of course it will work. I think it's probably best to just say that module_load_include() will work.

imalabya’s picture

StatusFileSize
new823 bytes
new851 bytes

Have made the asked changes.

imalabya’s picture

Status: Needs work » Needs review
jhodgdon’s picture

That looks fine to me, thanks!

Hm... I'm wondering if we should even mention module_load_include() though. Looking at the issue summary for #2351919: Replace uses of drupal_get_path() with __DIR__ where possible it is saying we should not be using

drupal_get_path() in where the simple use of __DIR__ would have been sufficient and more performant.

It seems like this would also be true for module_load_include()? What do you think? Maybe we should just not say anything about module_load_include() either. I don't know... @catch are you reading this?

dimaro’s picture

@jhodgdon Finally, Can I do something more on this issue? or we are waiting to @catch response?

jhodgdon’s picture

Status: Needs review » Needs work

Let's just take out the module_load_include mention sentence.

dimaro’s picture

Status: Needs work » Needs review
StatusFileSize
new659 bytes
new780 bytes

Apply changes mentioned on #32.

jhodgdon’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -needs backport to 8.0.x

Thanks! This looks fine to me.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -needs backport to 8.1.x

Committed 36f657b and pushed to 8.1.x and 8.2.x. Thanks!

  • alexpott committed 4e658ef on 8.2.x
    Issue #2667588 by dimaro, malavya, johnrosswvsu: Document that a module'...

  • alexpott committed 36f657b on 8.1.x
    Issue #2667588 by dimaro, malavya, johnrosswvsu: Document that a module'...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

fgm’s picture

Issue summary: View changes