themetman's picture

I am porting a couple of custom modules I wrote for myself in Drupal 8. One is a Block.
I have included one class at the beginning of the module file

require_once 'libraries/SunMoonFunctions.php';

and similarly in the SunMoonFunctions class I have used 'require_once' for more classes.
I can clear the cache using Drush with no errors, but when I create an instance of the class

$now = strtotime(date("Y/m/d h:i:s", time()));
$smfuncs = new SunMoonFunctions($now);

and load page with the block on it I get the following error: Class 'SunMoonFunctions' not found

I have looked through the API to see if there is a method to include a php library as you do with js, but cannot find one. Also I cannot find anything on the web about this.

I have tried using a namespace, but then the whole page will not load.

I have also included the file in my hook_autoload_info() function

function astro_stuff_autoload_info()
{
    return array(
        'AstroStuff' => 'astro_stuff.inc',
        'SunMoonFunctions' => 'libraries/SunMoonFunctions.php',
    );
}

but I still get the same error.
Any ideas would be welcome.

Accepted answer

In Backdrop, classes are included differently than in Drupal 7 or 8. You should not need either the require_once or module_load_include() calls, only the hook_autoload_info() function (https://api.backdropcms.org/api/backdrop/core%21modules%21system%21syste...). That is the way it is done for the Node, User, File, Comment, etc. classes in core.

I think you probably do not need

'AstroStuff' => 'astro_stuff.inc',

in astro_stuff_autoload_info().

Is there a class definition in astro_stuff.inc? If that is just a normal include file with regular functions, include it with module_load_include() and remove it from astro_stuff_autoload_info(). (Although it might not hurt to leave it there. Try it both ways.)

It's interesting that Nate did it the way he did in the GitHub API integration module.

Most helpful answers

Sanity check

- Can you dpm() in the autoload function to make sure its being called 

- Your files have .inc types and not .php?

- the libraries folder is in the module root?

- everything is spelt right?

the api site does say that `hook_autoload_info` uses relative paths though;

https://api.backdropcms.org/api/backdrop/core%21modules%21system%21syste...

 

> Note that all paths to classes are relative to the module that is implementing this hook. If you need to reference classes outside of the module root or modify existing paths, use hook_autoload_info_alter() instead.

so you might try the alter hook or `/libraries/YOURCLASSFILE` or move the YOURCLASSFILE to your `astro_stuff` module.

Comments

Hello @themetman;

The `backdrop-contrib/githubapi` module does it like this:

module_load_include('inc', 'githubapi', 'githubapi_class');

then it is able to create an instance of the `GitHubAPI` class.

 

------

I would have thought `hook_autoload_info` would have done it too, but I'll have to look into that.

oadaeh's picture

In Backdrop, classes are included differently than in Drupal 7 or 8. You should not need either the require_once or module_load_include() calls, only the hook_autoload_info() function (https://api.backdropcms.org/api/backdrop/core%21modules%21system%21syste...). That is the way it is done for the Node, User, File, Comment, etc. classes in core.

I think you probably do not need

'AstroStuff' => 'astro_stuff.inc',

in astro_stuff_autoload_info().

Is there a class definition in astro_stuff.inc? If that is just a normal include file with regular functions, include it with module_load_include() and remove it from astro_stuff_autoload_info(). (Although it might not hurt to leave it there. Try it both ways.)

It's interesting that Nate did it the way he did in the GitHub API integration module.

indigoxela's picture

hook_autoload_info is the right tool for the job.

But remember to always flush caches, whenever you change anything there. I'd bet that's what was tricking you.

the api site does say that `hook_autoload_info` uses relative paths though;

https://api.backdropcms.org/api/backdrop/core%21modules%21system%21syste...

 

> Note that all paths to classes are relative to the module that is implementing this hook. If you need to reference classes outside of the module root or modify existing paths, use hook_autoload_info_alter() instead.

so you might try the alter hook or `/libraries/YOURCLASSFILE` or move the YOURCLASSFILE to your `astro_stuff` module.

themetman's picture

Thanks you @serundeputy for getting back with a possible solution.

I have looked at the code on GitHub, and I have added a hook_get_class function and added this into it

module_load_include('inc', 'astro_stuff', 'SunMoonFunctions');

I have removed the require_once statement and moved the SunMoonFunctions.inc into  the root of the module so it is found by the module_load_include function.

drush cc all reports no errors.

Now I have the same error confirmed in the log as the place where I try and initilise the class as above:

Class 'SunMoonFunctions' not found

I am still floundering!

 

themetman's picture

Many thanks to @oadaeh and @indigoxela very informative.

OK, so I have removed the hook_get_class and it's content. and the astro_stuff_autoload_info now looks like this:

function astro_stuff_autoload_info()
{
    return array(
        'AstroStuff' => 'astro_stuff.inc',
        'SunriseSunsetFunctions' => 'SunriseSunsetFunctions.inc',
    );
}

I still get the error from the line I try and create a new instance of the class:

Class 'SunMoonFunctions' not found

I have no namespaces in any of the libraries I have, nor the astro_stuff.module file.

themetman's picture

Oh Dear!! Typo problem I should have loaded the SunMoonFunctions.inc file in the astro_stuff_autoload_info function!!!

So it now looks like this, and I can get to the class.

function astro_stuff_autoload_info()
{
    return array(
        'AstroStuff' => 'astro_stuff.inc',
        'SunMoonFunctions' => 'SunMoonFunctions.inc',
    );
}

Sorted!

Sanity check

- Can you dpm() in the autoload function to make sure its being called 

- Your files have .inc types and not .php?

- the libraries folder is in the module root?

- everything is spelt right?

themetman's picture

Thanks, @docwilmot I will put your logic where I can check it for the future.

All a good learning curve.

Regards

Ah you sorted it while I was typing. Good luck.