PHP autoloader not working - php

I seem to have some misconceptions on how autoloading works in PHP still, one I simply cannot explain.
I have a class called glue which has a spl_autoload_register within it's main function, here called run like so:
class glue{
public static function run(){
spl_autoload_register(array('glue','autoload'));
}
}
The autoload function works by loading via the PSR-0 standard and works from absolute paths. This is all tested as working etc. Note that glue is not namespaced.
The autoload function covers a namespace called glue. Within this namespace I have a error handler called \glue\ErrorHandler.
When I trigger an error the glue class will autoload \glue\ErrorHandler by PSR-0 notation from the root directory as defined by a stored ROOT constant. This has been tested as working as well in classes such as \glue\User and \glue\Session.
So now for the problem. I cause a Call-time pass-by-reference has been deprecated error within \glue\Validation and it doesn't seem to run my autoload function.
I can see how it is going into my autoload function for everything but when I call this error in that class it just seems to skip my autoloader and bail out saying it can't find my error handler class.
Normally I would say it is something with my programming but I have tried everything. I cannot explain how, for this one error. What compounds my confusion further is that if I cause a:
syntax error, unexpected T_ISSET in /media/server_ws/xxxxxxx/glue/Validation.php on line 47
Error it works. It seems to be for that one error it just will not autoload my error handler.
I thought this might be because my spl_autoload_register is not being binded to that namespace (since the error handler that works is actually called from within glue) and some how, maybe, it is randomly working. So from \glue\Validation I called a class I have never looked at: \glue\util\Crypt but that works and goes into the autoloader correctly.
When I call this error: Call-time pass-by-reference has been deprecated from within glue class it works perfectly.
Can anyone shed some light on this?
Edit
As requested here is a brievated version of Validation.php:
namespace glue;
use glue,
\glue\Exception,
\glue\Collection;
class Validation extends \glue\Component{
private function validateRule($rule){
// This is the line, notice the pass by reference down there?
$valid = $validator($field,$field_value,$params,&$this->model) && $valid;
}
}

The Call-time pass-by-reference has been deprecated error is thrown during script compilation, and auto-loading is disabled during compilation. It's disabled because the compiler cannot start compiling multiple scripts at the same time (i.e. it is not re-entrant), and auto-loading may load some script, which may require compiling it.
Source: https://github.com/php/php-src/blob/76ad52ccc501c02aeb068d2eb4f119ef6f0c2b6a/Zend/zend_execute_API.c#L1058

Related

Php 7.4.3 Class not found

This is my project path configuration
./create.php
/Install/Install.php
create.php
<?php
use Install\Install;
echo "Starting";
$install = new Install();
This gives me the error
PHP Fatal error: Uncaught Error: Class 'Install\Install' not found in /project/create.php:6
Install.php
<?php
namespace Install;
class Install
{
//whatever
}
Can someone explain me what is happening there ?
Obviously I guess that using a require_once line with my filename would probably fix the issue...but I thought using namespace and use import could prevent me from doing that like we do in classic framework like symfony / magento ?
I've seen some post speaking about autoloading, but i'm a little bit lost. Haven't been able to find a clear explanation on the other stack topic neither.
PHP compiles code one file at a time. It doesn't have any native concept of a "project" or a "full program".
There are three concepts involved here, which complement rather than replacing each other:
Namespaces are just a way of naming things. They allow you to have two classes called Install and still tell the difference between them. The use statement just tells the compiler (within one file) which of those classes you want when you write Install. The PHP manual has a chapter on namespaces which goes into more detail on all of this.
Require and include are the only mechanisms that allow code in one file to reference code in another. At some point, you need to tell the compiler to load "Install.php".
Autoloading is a way for PHP to ask your code which file it should load, when you mention a class it hasn't seen the definition for yet. The first time a class name is encountered, any function registered with spl_autoload_register will be called with that class name, and then has a chance to run include/require to load the definition. There is a fairly brief overview of autoloading in the PHP manual.
So, in your example:
use Install\Install; just means "when I write Install, I really mean Install\Install"
new Install() is translated by the compiler to new Install\Install()
the class Install\Install hasn't been defined; if an autoload function has been registered, it will be called, with the string "Install\Install" as input
that autoload function can then look at that class name, and run require_once __DIR__ . '/some/path/Install.php';
You can write the autoload function yourself, or you can use an "off-the-shelf" implementation where you just have to configure the directory where your classes are, and then follow a convention for how to name them.
If you want to Use class from another file, you must include or require the file.
Use require('Install.php'); before use Install\Install;.
If you are planning to do a big project I would recommend to use PHP frameworks rather than coding from scratch.

PHP - Class 'My\Engine\Control' not found

The following code is included by another file. My\Engine\Control is defined much earlier and extended all throughout my site with no issues. However in this one file I get the the error:
Fatal error: Class 'My\Engine\Control' not found in
/mnt/web/~/classes.php on line 6
<?php
namespace My\Engine;
// class Control {}
class RequiresAccount extends Control {
public function permissions() {
}
}
Yet when I try to put a dummy Control class in (uncomment the commented part) I get a different error.
Fatal error: Cannot declare class My\Engine\Control, because the name
is already in use in /mnt/web/~/Control.class.php on line 47
It seems impossible and I just can't figure it out. I write code like this all the time and just this one time...
All other files that require extending \My\Engine\Control function perfectly.
It seems that your using some custom autoload logic and some kind of optimizer which puts all the classes together into one file.
I would suggest sticking with PSR-4 standard & Composer library to support and maintain it.
This way your files will be organized and composer will take care of properly handling loading the files and optimizing the loading process for production. All you need to do is to include ./vendor/autoload.php file into your project and define the auto-loading strategy in composer.json file.

PHP5.5: Fatal error: Cannot redeclare class

since I upgraded from PHP 5.2 to 5.5 I get an error I don't understand by now.
Fatal error: Cannot redeclare class sessionHandler in ... on line ...
Well before updating the PHP version this error didn't raise and redeclaring a class should be an error independent from PHP version as I guess. Further I always use require_once() which should help to avoid a mistake on that.
So just to make sure it doesn't be redeclared, I added a backtrace code block before that class declaration. So hopefully, I thought it would output twice, but I get only one backtrace output at all. Therefore it gets declared only once from my point of few.
Do I miss something? Any idea how to find the "real" issue?
Class "SessionHandler" already exists in the namespace as it's a class in PHP - http://php.net/manual/en/class.sessionhandler.php
Looks like the class was included in PHP 5.4 so it explains everything.
Try to think of some other name for the class or define a namespace.
If you create a namespace, something like..
namespace App;
class sessionHandler {
....
you won't get the error anymore but you will need to use App\sessionHandler whenever you're referring to your own class.

spl autoloading: Class is not found – namespace issue?

I am just getting my feet wet with PHP autoloading. I actually think I got the basics down, but somehow it still won't work.
I got the following directory structure:
myLib
-bootstrap.php
-sven
-project
project.php
bootstrap.php is the file that will be included to use the lib. In this file, I simply have the following code:
spl_autoload_extensions('.php');
spl_autoload_register();
$var = new \sven\project\project();
$var->init();
And in project.php:
namespace sven\project;
class project {
public function init() {
echo 'It works!';
}
}
The way the autoloader is used, to my understanding, the core PHP autoloader should translate the namespace into directories and then look for a php containing the class.
Instead of displaying 'It works!', a fatal error is thrown. Unfortunately, I can't exactly tell what that error is because the CMS only informs me that there was a fatal error.
But with such a simple structure, I am sure the error is pretty basic and easy to find for someone who knows how it works.
Where am I going wrong with this example – did I correctly describe how the autoloader should work in this setup or is there a misunderstanding?
EDIT: Finally got the error log running:
Fatal error: Class undefined: sven\\project\\project\\project\\project in /xxx/bootstrap.php on line 36
That obviously looks wrong, but how to change that? Why are there two backslashes?
spl_autoload_extensions('.php');
spl_autoload_register();
This code works only with PHP 5.3 and above.
Sven,
I just answered another question about spl_autoload, try my example click here
I hope it helps!
PS:
Also don't just autoload all .php files on your path , that can be dangerous !

PHP __autoload Cannot redeclare

I started to use the PHP __autoload function and now I'm getting those weird Fatal error: Cannot redeclare class xxx errors.
It's weird since these errors occur on classes I don't even load with the autoload function. And I also use require_once to include the files.
I'm really puzzled about this. Anyone knows anything about this kind of errors when using autoload?
require_once/include_once only looks at the file name when they're trying to include a file, not a class name. So you can have class Foo in both Foo.php and B.php, and then you'll get that error.
I'm not sure how __autoload would cause you any problems, unless __autoload requires Foo.php because it needs class Foo, and you require B.php manually which redefines class Foo.
By the way, use spl_autoload_register instead of __autoload.
i had same situation .. all i changed was and its working for me
include('xxx.php');
to
require_once('xxx.php');
I am not pretend on the best answer. Just my thoughts.
__autoload() is deprecated in PHP 7.2 and will be possiblly deleted.
I found this way to upload/include files
//initialize a function which will upload files
function upload(){//you can call the function as you like
//your path to files goes here
}
spl_autoload_register('upload')//specify the function, where you include your files(in this case it's upload function
I've had this before, not sure what caused it though. Make sure you're using require_once/include_once rather than the normal versions for starters. I think the problem was related to using class_exists without telling it to skip autoloading (class_exists($name, false)) - are you doing this?
I found the problem. Apparently when it wanted to include Bank class, it took the "bank.php" file from the current directory ^^. Which is just the bank page, it should have include "src/model/Bank.php". I removed the current directory from the search list and it has been fixed.
So always make sure the autoload function is including the correct files. Good practice is too name your files more straightforward like class.Bank.php or class.User.php instead of Bank.php or User.php.
Thanks for your help and quick response anyway!

Categories