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
| Comment | File | Size | Author |
|---|---|---|---|
| #33 | document_that_a-2667588-33.patch | 780 bytes | dimaro |
| #33 | interdiff-2667588-28-33.txt | 659 bytes | dimaro |
| #28 | inetrdiff-21-28.txt | 851 bytes | imalabya |
| #28 | document_that_a-2667588-28.patch | 823 bytes | imalabya |
| #21 | interdiff-2667588-19-21.txt | 892 bytes | dimaro |
Comments
Comment #2
jhodgdonYou'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?
Comment #3
joachim commented> 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.
Comment #4
jhodgdonOK let's only do this for hook_requirements() then.
Comment #5
dimaro commentedI'm working on it
Comment #6
dimaro commentedI 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!
Comment #7
jhodgdonThat looks right to me, thanks!
Comment #8
catchNot 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?
Comment #9
joachim commentedI 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.
Comment #10
jhodgdonHm. 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?
Comment #11
dimaro commentedWhat is the status of this issue?
Can I do something?
Thanks!
Comment #12
jhodgdonIt 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.
Comment #13
dimaro commentedI try to fix #12.
Could be a first approach?
Comment #14
joachim commentedThis looks good, except for one thing:
either load the class, or... ?
Comment #15
joachim commented> 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:
I'll file an issue.
Comment #16
dimaro commentedFix #14.
On #15 I have a doubt.
Another issue?
Comment #17
joachim commentedYup, I filed #2681929: drupal_check_profile() should not register a profile's modules with the autoloader.
Comment #18
joachim commentedThanks! 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'?
Comment #19
johnrosswvsu commentedI 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.
Comment #20
jhodgdonThanks! Looking pretty close...
Just say "... you'll need to include the class file directly". Otherwise... what does "load the class" mean?
Comment #21
dimaro commentedPatch to apply changes mentioned on #20.
Comment #22
joachim commentedLooks good to me.
Comment #23
jhodgdonThanks! +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.
Comment #24
catchWe'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.
Comment #25
dimaro commented@jhodgdon We only have to replace drupal_get_path() for __DIR__? or it needs some more work?
Comment #26
joachim commentedThe behaviour may be by design, by the absence of documentation about it is the bug.
Comment #27
jhodgdonRE #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.
Comment #28
imalabyaHave made the asked changes.
Comment #29
imalabyaComment #30
jhodgdonThat 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
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?
Comment #31
dimaro commented@jhodgdon Finally, Can I do something more on this issue? or we are waiting to @catch response?
Comment #32
jhodgdonLet's just take out the module_load_include mention sentence.
Comment #33
dimaro commentedApply changes mentioned on #32.
Comment #34
jhodgdonThanks! This looks fine to me.
Comment #35
alexpottCommitted 36f657b and pushed to 8.1.x and 8.2.x. Thanks!
Comment #39
fgm