PHP autoload with namespaces do not load file - php

I have an issue with my autoloader and namespaces.
Below the autoloader
<?php
spl_autoload_register( function( $class ) {
$folder = 'include/';
$prefix = 'class.';
$ext = '.php';
$fullPath = $folder . $prefix . $class . $ext;
if( !file_exists( $fullPath ) ){
print 'Class file not found!';
return false;
}
require_once $fullPath;
});
?>
Below the index file
<?php
require 'autoload.php';
//use backslash for namespace
$pers = new Person\Person();
?>
The file for the class Person is saved in the directory root->include->Person
I used the namespace in the class file like this
<?php
namespace Person;
class Person{
function __construct(){
print 'autoload works';
}
}
?>
If I visit the index file in the browser it returns 'Class file not found'.
Do I use the namespace correctly?

Change your autoload code a little
<?php
spl_autoload_register( function( $class ) {
$folder = 'include/';
$prefix = '.class';
$ext = '.php';
//replace the backslash
$fullPath = $folder . str_replace( "\\", '/', $class ) . $prefix . $ext;
if( !file_exists( $fullPath ) ){
print 'Class file not found!';
return false;
}
require_once $fullPath;
});
?>

You try to include
Include/class.Person\Person.php
If your Os is linux, you must know that have different between / and \
Prefix class is exist in folder name?

Related

Autoloading with namespaces

My structure:
/test/init.php
/test/sub/Info.php
init.php:
<?php
namespace test;
$namespaces = function($path) {
//echo $path; = test\sub\Info
if (preg_match('/\\\\/', $path)) {
$path = str_replace('\\', DIRECTORY_SEPARATOR, $path);
}
//echo $path; = test\sub\Info
if (file_exists("{$path}.php")) {
require_once("{$path}.php");
}
};
spl_autoload_register($namespaces);
$info = new sub\Info();
And Info.php:
<?php
namespace test\sub;
class Info
{
public function __construct()
{
echo 123;
}
}
Why this isn't working?
I use Windows, so why DIRECTORY_SEPARATOR == \?
EDIT:
Sorry, I updated my question. I forgot to paste spl_autoload_register on stackoverflow.
Your autoloader ideally needs to be defined outside of a namespace, at the top level of the directory structure - the way you've got it set up at the moment, it's trying to include the file test/sub/Info.php from within the test directory, rather than from the root (i.e. test/test/sub/Info.php, which doesn't exist)
If you remove the namespace prefix test from both files (so remove it entirely from init.php and just have namespace sub; in sub/Info.php) then it will work correctly. The other option would be to move the autoloader into a file in the root directory, so that the namespaces again match up with the file-system layout.
You are using a relative path, so there are several things that could be wrong... You can see which is the current working directory by doing:
echo getcwd();
You could also try something like this:
$namespaces = function($class) {
$basepath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR;
$file = $basepath . str_replace('\\', DIRECTORY_SEPARATOR, $class) . ".php";
if (!file_exists($file) || !is_readable($file)) {
return false;
}
require_once($file);
return class_exists($class, false);
};
Variable $basepath could be also a defined constant, or a variable from a config file...

Spl_Auto_register not loading class properly

I'm trying to learn about spl_autoload_register().
My index.php is under document root, my MyClass.php is put under document root /MyProject/MyClass/MyClass.php
Here's my index.php
<?php
define('CLASSDIR', 'mylib');
define('BASEPATH', #realpath( dirname (__FILE__).'/../').'/'.CLASSDIR);
spl_autoload_register(null, false);
spl_autoload_extensions('.php');
// PSR-0 provided autoloader.
function autoLoader($className){
$className = ltrim($className, '\\');
$fileName = '';
$namespace = '';
if ($lastNsPos = strrpos($className, '\\')) {
$namespace = substr($className, 0, $lastNsPos);
$className = substr($className, $lastNsPos + 1);
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
}
$fileName .= BASEPATH.'/'.str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
require $fileName;
}
spl_autoload_register('autoLoader');
$obj = new MyClass();
$obj->test();
?>
Here's my Class: MyClass.php
<?php
namespace MyProject\MyClass;
class MyClass{
public function __contruct(){
echo('weird');
}
function test(){
echo 'issue';
}
}?>
Here's the error:
Fatal error: Call to undefined method MyClass::test() in /path/to/file/index.php on line 26
So, I'm assuming it found the class (since it didn't complain)? But the messages 'weird' and 'issue' are not displayed. Telling me that the constructor didn't fire.
Okay, assuming your class file is located in a seperate folder called classes (example)
Structure like this:
DOCUMENT_ROOT/
->index.php
->classes/
->Myclass/
->Myclass.php
Somewhere on your index.php You'd have something looking like this:
<?php
DEFINE('__BASE', realpath(dirname(__FILE__)));
require_once('load.php');
?>
Now your load.php file should have the __autoload() function in there, looking something like this:
// Auto load function to load all the classes as required
function __autoload($class_name) {
$filename = ucfirst($class_name) . '.php';
$file = __BASE . DIRECTORY_SEPARATOR .'classes/' . ucfirst($class_name) . $filename;
// First file (model) doesnt exist
if (!file_exists($file)) {
return false;
} else {
// include class
require $file;
}
}
EDIT:
If you'd like to do it with spl_autoload_register(), you'd have something similar to this in your load.php
// Auto load function to load all the classes as required
function load_classes($class_name) {
$filename = ucfirst($class_name) . '.php';
$file = __BASE . DIRECTORY_SEPARATOR .'classes/' . ucfirst($class_name) . $filename;
// First file (model) doesnt exist
if (!file_exists($file)) {
return false;
} else {
// include class
require $file;
}
}
spl_autoload_register('load_classes');

Php autoload project

I've a project like this:
Now i want to autoload all the php files in the folder classes and sub folders.
I can do that with this:
$dirs = array(
CMS_ROOT.'/classes',
CMS_ROOT.'/classes/layout',
CMS_ROOT.'/classes/layout/pages'
);
foreach( $array as $dir) {
foreach ( glob( $dir."/*.php" ) as $filename ) {
require_once $filename;
}
}
But i dont like this. For example.
"layout/pages/a.php" extends "layout/pages/b.php"
Now i get an error because a.php was loaded first. How do you people load your project files? Classes?
SOLVED :)
This is my code now:
spl_autoload_register('autoloader');
function autoloader($className) {
$className = str_replace('cms_', '', $className);
$className = str_replace('_', '/', $className);
$file = CLASSES.'/'.$className.'.php';
if( file_exists( $file ) ) {
require_once $file;
}
}
You should try this
<?php
spl_autoload_register('your_autoloader');
function your_autoloader($classname) {
static $dirs = array(
CMS_ROOT.'/classes',
CMS_ROOT.'/classes/layout',
CMS_ROOT.'/classes/layout/pages'
);
foreach ($dirs as $dir) {
if (file_exists($dir . '/'. $classname. '.php')) {
include_once $dir . '/' . $classname . '.php';
}
}
}
After registering your_autoloader with spl_autoload_register() it will be called by the php interpreter every time you access a class that:
Has not already been loaded with require_once() or include_once()
Is not part of the PHP internals

PHP autoload oddity

function __autoload($class_name) {
echo("Attempting autoload ");
if (substr($class_name, -6) == "Mapper") {
$file = 'mappers/'.$class_name.'.php';
echo "Will autoload $file ";
include_once($file);
}
}
__autoload("UserMapper");
$user = new UserMapper($adapter);
die("done");
Result:
Attempting autoload Will autoload mappers/UserMapper.php done
function __autoload($class_name) {
echo("Attempting autoload ");
if (substr($class_name, -6) == "Mapper") {
$file = 'mappers/'.$class_name.'.php';
echo "Will autoload $file ";
include_once($file);
}
}
//__autoload("UserMapper");
$user = new UserMapper($adapter);
die("done");
(I just commented out the manual call to __autoload()...)
Result:
Fatal error: Class 'UserMapper' not found in C:\Program Files\EasyPHP-5.3.5.0\www\proj\29letters\login.php on line 13
Any ideas?
And yes, I'm running PHP 5.3.5
Not sure why your example isn't working, as it should be as per the manual.
Have you tried using spl_autoload_register to register the autoloader function?
Have you set a proper include_path? You're using a relative path to include the class's file. Try an absolute path instead.
$dir = __DIR__ . '/../path/to/mappers';
$file = $dir . '/' . $class_name . '.php';
require $file;
or
// do this outside of __autoload
set_include_path(get_include_path() . PATH_SEPARATOR . __DIR__ . '/../path/to/mappers';
// inside __autoload
$file = $class_name . '.php';
require $file;

Namespace Autoload works under windows, but not on Linux

I have the following php code:
index.php
<?php
spl_autoload_extensions(".php");
spl_autoload_register();
use modules\standard as std;
$handler = new std\handler();
$handler->delegate();
?>
modules\standard\handler.php
<?php
namespace modules\standard {
class handler {
function delegate(){
echo 'Hello from delegation!';
}
}
}
?>
Under Windows 7, running WAMP, the code produces the message "Hello from Delegation!" however under Linux, I get the following:
Fatal error: spl_autoload(): Class modules\standard\handler could not be loaded in /var/www/index.php on line 15
Windows is running PHP 5.3.0 under WAMP, and Linux is running the 5.3.2 dotdeb package under Ubuntu 9.10.
Is this a configuration issue on my linux box, or just a difference in the way namespaces and autoloading is handled on the different operating systems
The SPL autoloader is extremely primitive - it has no knowledge of namespaces, so it tries to load a file with \ in it's name while on Linux/Unix the path separator is / not .
Herman Radtke says he has submitted a patch :
http://www.hermanradtke.com/blog/hidden-features-with-spl_autoload-and-namespaces/
:s
I'm hoping it'll be implemented soon.
For now I use this workaround :
<?php
set_include_path( './classes/' . PATH_SEPARATOR . get_include_path() );
spl_autoload_extensions( '.php , .class.php' );
spl_autoload_register();
function linux_namespaces_autoload ( $class_name )
{
/* use if you need to lowercase first char *
$class_name = implode( DIRECTORY_SEPARATOR , array_map( 'lcfirst' , explode( '\\' , $class_name ) ) );/* else just use the following : */
$class_name = implode( DIRECTORY_SEPARATOR , explode( '\\' , $class_name ) );
static $extensions = array();
if ( empty($extensions ) )
{
$extensions = array_map( 'trim' , explode( ',' , spl_autoload_extensions() ) );
}
static $include_paths = array();
if ( empty( $include_paths ) )
{
$include_paths = explode( PATH_SEPARATOR , get_include_path() );
}
foreach ( $include_paths as $path )
{
$path .= ( DIRECTORY_SEPARATOR !== $path[ strlen( $path ) - 1 ] ) ? DIRECTORY_SEPARATOR : '';
foreach ( $extensions as $extension )
{
$file = $path . $class_name . $extension;
if ( file_exists( $file ) && is_readable( $file ) )
{
require $file;
return;
}
}
}
throw new Exception( _( 'class ' . $class_name . ' could not be found.' ) );
}
spl_autoload_register( 'linux_namespaces_autoload' , TRUE , FALSE );
?>
function __autoload($class_name) {
$paths[] = dirname(__FILE__) . "/../libs/misc/";
$paths[] = dirname(__FILE__) . "/../../libs/misc/";
$paths[] = dirname(__FILE__) . "/../../libs/helpers/";
$paths[] = dirname(__FILE__) . "/../../libs/simpleimage/";
foreach($paths as $path)
{
if(file_exists($path.strtolower($class_name).'.class.php')){
require_once($path.strtolower($class_name).'.class.php');
}
}
}
function __autoload($class_name)
{
$class_name = strtolower(str_replace('\\', DIRECTORY_SEPARATOR, $class_name));
include $class_name . '.php';
}
The srttolower is needed on Apache because it is (contrary to IIS) case sentive.
This is a common problem occurs when autoloading. The fix is to use DIRECTORY_SEPARATOR constant in the autoload function.
So your autoload function will look like following
<?php
spl_autoload_register(function($className) {
$className = str_replace("\", DIRECTORY_SEPARATOR, $className);
include_once $_SERVER['DOCUMENT_ROOT'] . '/class/' . $className . '.php';
});
If you need to learn more on namespace/class autoloading visit here
Thanks.

Categories