0

This code works fine on my dev machine (Windows) but on the server it fails to load the classes:

set_include_path(get_include_path() . PATH_SEPARATOR . 'class/');
spl_autoload_extensions('.class.php');
spl_autoload_register();

I've checked the include path and that seems OK. I also attempted to include a absolute path thusly:

$application_root = $_SERVER['DOCUMENT_ROOT'];
set_include_path(get_include_path() . PATH_SEPARATOR . $application_root.'/class/');

with much the same result: the class is not loaded;

This however works:

$autoloader = function( $class_name )
{
  $application_root = $_SERVER['DOCUMENT_ROOT'];
  $filename = $application_root . '/class/' . str_replace( '\\', '/', $class_name)  . '.class.php';
  require_once $filename;
};

spl_autoload_register( $autoloader );

But is not as elegant.

How do I get spl_autoload_extensions working on my production machine?

Summary

not working;

set_include_path(get_include_path() . PATH_SEPARATOR .getenv('DOCUMENT_ROOT').'/class');
spl_autoload_extensions('.class.php');
$filter = new Filter();

With get_include_path() I do get a complete path ".:/usr/share/pear:/usr/share/php:/home/httpd/vhosts/_hidden_/httpsdocs/class". I get Fatal error: Class 'Filter' not found.

working:

include getenv('DOCUMENT_ROOT').'/class/Filter.class.php';
$filter = new Filter();
theking2
  • 2,174
  • 1
  • 27
  • 36
  • This is probably related to the "\" vs "/" problem. Check this S.O question/answer: [https://stackoverflow.com/a/2876935/17087765](https://stackoverflow.com/a/2876935/17087765) – slashroot Nov 13 '21 at 11:31
  • аdd filenames in class directory. you don't need call `spl_autoload_register();` - default loader already registred – WinterSilence Nov 13 '21 at 17:24
  • That is an interesting observatino @slashroot but contradicts the behaviour. On my Windows machine the code with `'class/'` works on linux it does not. – theking2 Nov 15 '21 at 16:18
  • @WinterSilence do you mean that by just adding a directory called `class` php automachically finds the class files? – theking2 Nov 15 '21 at 16:19
  • @theking2 So just curious on your linux machine after you use `set_include_path(get_include_path() . PATH_SEPARATOR . 'class/');` if you `echo get_include_path()` does it show the right information? ALSO you should note that when you use `set_include_path()` it is only valid for the duration of that script's execution. Your best option is to use the `spl_autoload_register` – slashroot Nov 15 '21 at 17:01
  • @theking2 In response to WinterSilence's comment you might want to read the first comment here: [What is Autoloading; How do you use spl_autoload, __autoload and spl_autoload_register?](https://stackoverflow.com/a/7987085/17087765). Very useful and will probably do exactly what your looking for. – slashroot Nov 15 '21 at 17:05
  • @theking2 for example ` – WinterSilence Nov 15 '21 at 20:03
  • @slashroot thanks I think I have that all covered. Unless you see something that I didn't include – theking2 Nov 16 '21 at 11:22
  • @slashroot I have this in a utils.php file that I `require_once` as first in virtualla all other php files. – theking2 Nov 16 '21 at 11:23
  • The following `echo wrap_tag('p', get_include_path()); set_include_path(get_include_path() . PATH_SEPARATOR . 'class/'); echo wrap_tag('p', get_include_path());` gives me: `.:/usr/share/pear:/usr/share/php` and `.:/usr/share/pear:/usr/share/php:class/` – theking2 Nov 20 '21 at 13:42

1 Answers1

-1

Solved

What hinted me was the case-insensitivity on Windows OS (the file system is btw.) where linux does not ignore case. The documentation on php.net is sometimes particularly unclear or incomplete. What it didn't say is that it does a strtolower on the generated file (or even path) name.

I had to rename my class files Filter.class.php and YearFilter.class.php to filter.class.php and yearfilter.class.php and so on and so-fort but at the same time keeping the class names abstract class Filter {} and class Yearfilter{} extends Filter` the classes were loaded.

Also I have to disagree with @WinterSilence. The spl_autoload_register() had to be called at least once or the class files were not loaded.

Renaming the class files

The following code worked after renaming all my class file to have lowercase characters only.

<?php
spl_autoload_register();

set_include_path(get_include_path() . PATH_SEPARATOR . 'class/');
spl_autoload_extensions('.class.php');

$f = new Filter();

I know it works by php complaining about Filter being abstract.

Surpassing the build-in autoloader:

Without renaming the class files (which is silly and will cause future bugs). The spl_autoload_extensions has no effect btw.:

<?php

set_include_path(get_include_path() . PATH_SEPARATOR . 'class/');
spl_autoload_extensions('.class.php');
spl_autoload_register(function($class_name) { require_once( $class_name.'.class.php' );},true);
$f = new Filter();

Btw this is already filed as a bug and marked as will not fix as it will break buggy php code that depends on it. Although a patch exists it seem not to have made it in current PHP releases.

EDIT: Btw the main reason of this behavior not being fixed is that whereas everything else is, in php neither class names nor function names are case-sensitive. class FooBar{} equals class FOOBAR{} equals foorbar{}. Having class names case insensitive it makes no sense to have the filename reflect the contents as it can't, really.

theking2
  • 2,174
  • 1
  • 27
  • 36
  • > Also I have to disagree with @WinterSilence. The spl_autoload_register() had to be called at least once or the class files were not loaded. maybe it's true for your configuration and php version, but it's work by default – WinterSilence Jan 14 '22 at 14:35
  • @wintersilence: state the os you are testing on – theking2 Jan 15 '22 at 16:52