Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

In my theme directory I have the following structure:

/includes/functions-custom.php
/includes/avatax/AvaTax.php
/includes/classes/gmaps.class.php

I'm making a call from the functions-custom.php to include the second file within the WordPress admin using this code

require_once('avatax/AvaTax.php'); //Avalara Sales Tax API
if ( is_admin() ) {
    require_once('classes/gmaps.class.php');
}

The first require applies to both the theme and to the admin. The second, obviously, only applies to the admin. However, the first require fails with the following message:

Warning: require_once(/Users/philipdowner/Sites/dms/wp-content/themes/dms/includes/avatax/classes/BatchSvc/WP_User_Search.class.php) [function.require-once]: failed to open stream: No such file or directory in /Users/philipdowner/Sites/dms/wp-content/themes/dms/includes/avatax/AvaTax.php on line 23

Fatal error: require_once() [function.require]: Failed opening required '/Users/philipdowner/Sites/dms/wp-content/themes/dms/includes/avatax/classes/BatchSvc/WP_User_Search.class.php' (include_path='.:/Applications/MAMP/bin/php5/lib/php') in /Users/philipdowner/Sites/dms/wp-content/themes/dms/includes/avatax/AvaTax.php on line 23

I don't feel like this should be such a stumper. Perhaps I'm overlooking something obvious? I've tried preceding the file path with the constant 'TEMPLATEPATH' and using the obvious WordPress functions like

require_once(get_template_directory().'/path/to/file');

I'm developing locally on MAMP. Particularly odd is the call to the file (in the error message) '/classes/BatchSvc/WP_User_Search.class.php'.

Can anyone help?

share|improve this question
    
I marked the appropriate solution. –  manifestphil Sep 24 '12 at 14:08
    
Missed that completely, as it stays on bottom. Btw: You have PHP 5.3+, right? –  kaiser Sep 24 '12 at 17:08

4 Answers 4

Avoid native php functions

  1. They are not relative, so breaking stuff is easy. (like in the OPs case)
  2. Why role your own if core got a function for you?
  3. They don't consider edge cases

You should NEVER use the constants

  • STYLESHEET_DIRECTORY
  • TEMPLATE_DIRECTORY
  • WP_PLUGIN_DIR
  • etc...

Remember: Those are not API! and can therefore change!

but INSTEAD USE the following API functions:

  • Parent Theme: get_template_directory() / get_template_directory_uri()
  • Child Theme: get_stylesheet_directory() / get_stylesheet_directory_uri()

You can use both in Plugins and Themes:

  • plugin_dir_path(__FILE__).'/your/path/to/file.ext *) for Themes also
  • plugin_dir_url( __FILE__ ).'/your/path/to/file.ext

but plugin_dir_url() is reserved only for Plugins.

Keep in mind...

That there're

  • Plugins
  • MU-Plugins
  • Drop-Ins
  • Themes
  • Themes in directories registered via register_theme_directory( $dir );

So please stick with the native API functions like wp_upload_dir();, content_url();, etc.

In general: Take a look at /wp-includes/link-template.php for a whole bunch of nice path and URl related API functions.

share|improve this answer

It looks like the require is being called from within AvaTax.php, so if you change the call to ../classes/gmaps.class.php (in AvaTax.php, not in functions-custom.php) it should fix the error.

share|improve this answer
    
I think this is closer to the root problem. Try including get_template_directory() in all uses of require() or include(), so as to avoid relative-path problems such as this one. –  Chip Bennett Feb 10 '12 at 15:24
up vote 0 down vote accepted

So after a night of sleep, and confirmation from the above users that I was including files properly, I've managed to resolve the issue.

In the AvaTax.php file, there was an __autoload() function:

<?php
function __autoload($class_name) 
{   

if ( $class_name != 'WP_User_Search' ) { //WORDPRESS HACK
    $path=dirname(__FILE__).'/classes/'.$class_name . '.class.php';

    if(!file_exists($path))
    {
        $path=dirname(__FILE__).'/classes/BatchSvc/'.$class_name . '.class.php';

    }

    require_once $path;
}


}
?>

The function is being passed a variable from WordPress - $class_name. I'm not entirely sure where the variable comes from, but could probably dump the $_GLOBALS or $wp_query and find out. I've basically ensured (hacked) the function to ensure that the variable passed doesn't match the string 'WP_User_Search'.

As for my include files I've used the following code:

<?php
define('INCLUDE_PATH', get_template_directory().'/includes');
require_once(INCLUDE_PATH.'/avatax/AvaTax.php'); //Avalara Sales Tax API
if ( is_admin() ) {
require_once(INCLUDE_PATH.'/classes/gmaps.class.php');
}
?>

Thanks for helping me work thru this one guys!

share|improve this answer
    
So it's only for parent themes? –  kaiser Feb 10 '12 at 18:38

Manifestphil, if you use WordPress Autoloader, you don't have to worry about loading files of classes. Of course you have to write clean class files on this case, which also makes your code more manageable.

Easy steps:

  • Create folder /lib inside your theme root folder
  • To avoid problems with same class names, use namespaces and create appropriate folders structure
  • Write your code wisely to support classes autoload. Divide code into classes, so that classes are loaded only when absolutely necessary. Avoid big class files.

For example to load class MyNameSpace\MyClass you need folders structure shown below:

/mytheme
   /lib
      /MyNameSpace
         /MyClass.php

If you initialize new object or call some method etc, your class file is automatically loaded. Also it works really fine with any WordPress hooking method, for example:

add_action ( 'admin_menu', 'MyNameSpace\MyClass::AddSomeToolsMenu' );

On case above your class is loaded only when actually needed and called by WordPress :)

share|improve this answer
    
You can user WordPress Autoloader plugin: - bitbucket.org/holyfield/wp-autoloader –  D.A.H Apr 10 '13 at 1:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.