I have a folder structure that looks like
base_dir-
Includes.php
Libs-
Database.php
Log.php
Cofing.php
Models-
someClass.php
Scheduled-
test.php
My Includes.php has
spl_autoload_register(NULL, FALSE);
spl_autoload_extensions('.php, .class.php, lib.php');
function libLoader($name) {
$file = 'Libs/' . $name . '.php';
if (!file_exists($file)) {
// throw new Exception("Error Loading Library: $file does not exists!", 1);
return FALSE;
}
require_once $file;
}
function modelLoader($name) {
$file = 'Models/' . $name . '.php';
if (!file_exists($file)) {
// throw new Exception("Error Loading Library: $file does not exists!", 1);
return FALSE;
}
require_once $file;
}
spl_autoload_register('libLoader');
spl_autoload_register('modelLoader');
My someClass.php has
require_once '../Includes.php';
class someClass extends Database
{
public function __construct() { return 'hello world'; }
}
And test.php has
require_once '../Includes.php';
try {
$loads = new someClass();
} catch (Exception $e) {
echo "Exception: " . $e->getMessage();
}
When I run test.php I get someClass not found on .../Scheduled/test.php
Does spl works with extended classes like someClass.php or do I need to include the class to be exended?
And why it wouldnt find someClass.php?
Thanks
Change
$file = 'Models/' . $name . '.php';
to
$file = __DIR__ . '/Models/' . $name . '.php';
in your models autoloader (and the equivalent in your libLoader) to ensure that it's searching from the correct directory, and not the directory where your test.php file is located
Related
I am working on a PHP project and I am still learning how to apply namespaces to it. I've come up with the following situation:
File structure is
app.php
index.php
bar.php
sandbox
\_index.php
\_Foo.class.php
The contents of the files are as follows:
app.php
<?php
function strtocapital($string)
{
return substr(strtolower($string), 0, strrpos($string, '/')) . substr(strtoupper($string), strrpos($string, '/'), 2) . substr(strtolower($string), strrpos($string, '/') + 2);
}
function autoloader($className)
{
$path = __DIR__ . '/' . strtolower($className) . '.php';
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
$className = str_replace('\\', '/', $className);
$path = __DIR__ . '/' . strtolower($className) . '.php';
}
if (!is_file($path)) {
$className = strtocapital($className);
$path = __DIR__ . '/' . $className . '.class.php';
if (!is_file($path)) {
return false;
}
}
include_once $path;
echo "Successfully loaded ${className}<br>";
}
spl_autoload_register("autoloader");
index.php
<?php
require 'app.php';
use Sandbox\Foo as Fuu;
echo __DIR__ . '<br>';
$foo = new Fuu();
try {
echo $foo::FOOFOO;
$foo::foofoofoo();
} catch (Exception $e) {
print_r($e);
}
bar.php
<?php
class Bar
{
const BARBAR = "dada";
public static function barbarbar()
{
echo "Bar bar bar";
}
}
sandbox/index.php
<?php
require '../app.php';
use Bar;
echo __DIR__ . '<br>';
$bar = new Bar();
try {
echo $bar::BARBAR;
$bar::barbarbar();
} catch (Exception $e) {
print_r($e);
}
sandbox/Foo.class.php
<?php
class Foo
{
const FOOFOO = "bla";
public static function foofoofoo()
{
echo "Foo foo foo";
}
}
Despite the fact I receive both successful messages:
Successfully loaded Sandbox\Foo
Successfully loaded Bar
I only see the outputs for Bar class. The difference between them is that sandbox/index.php returns HTTP Status 200 and index.php returns HTTP Status 500. However, I see no errors, even after trying error_reporting(E_ALL).
Please help me on this, because doing the same steps for both classes and having one working and the other not is driving me nuts.
Thanks in advance.
By applying namespace at the top of the page that is using the bar or foo namespace it will define the namespace and work. Do this like so:
namespace foo; #Or namespace bar; or whatever your namespace is.
You can apply that on any page that you need to use that namespace on. A good tutorial on this would be https://www.sitepoint.com/php-53-namespaces-basics/.
I have coded a PHP script that includes every file in a directory. But im wondering if there is a way to load the classes in the files im including like a autoloader or something?
<?php
define("include_dir", dirname(__FILE__) . '/includes/');
foreach (scandir(include_dir) as $filename)
{
if (is_file(include_dir . '/' . $filename))
{
//its a php file, lets do this!
if (substr($filename, -4) == '.php')
{
include include_dir . $filename;
}
}
}
?>
try this-
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
the manual -
http://php.net/manual/en/language.oop5.autoload.php
In file: deckclass.php , with DOCROOT set to /var/www/Proj/application/controllers
getting error: Fatal error: Class 'Cardclass' not found in /var/www/Proj/application/controllers/deckclass.php on line 38
Why is it searching current php file and not DOCROOT folder?
function __autoload($class_name)
{
//class directories
$filename = DOCROOT .strtolower($class_name) . ".php";
if ( file_exists($filename) )
{
require_once ($filename);
}
else {
throw new Exception("Unable to load $class_name.");
}
}
$card = new Cardclass();
You can use define('ROOT', dirname(__FILE__)); and define('DS', DIRECTORY_SEPARATOR);
Tip
spl_autoload_register() provides a more flexible alternative for
autoloading classes. For this reason, using __autoload() is
discouraged and may be deprecated or removed in the future.
So do code should look like this:
<?php
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__FILE__)); //This is full path
spl_autoload_register('Autoloader'); //You can use annonymous function here
function Autoloader($class_name){
$filename = ROOT.DS.strtolower($class_name).".php";
var_dump($filename);
if(file_exists($filename)){
require_once ($filename);
}else{
throw new Exception("Unable to load ".$class_name."in".$filename);
}
}
$card = new Cardclass();
With __autoload:
<?php
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__FILE__)); //This is full path
function __autoload($class_name){
$filename = ROOT.DS.strtolower($class_name).".php";
var_dump($filename);
if(strpos($class, 'CI_') !== 0) {
if(file_exists($filename)){
require_once ($filename);
}else{
throw new Exception("Unable to load ".$class_name."in".$filename);
}
}
}
$card = new Cardclass();
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');
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;